[asp.net mvc 奇淫巧技] 06 - 也许你的项目同一个用户的请求都是同步的
一、感慨
很久前看到一篇博客中有句话大致的意思是:“asp.net 程序性能低下的主要原因是开发人员技术参差不齐”,当时看到这句话不以为然,然而时间过的越久接触的.net 开发人员越多就越认同这句话;特别最近发现非常一个成熟的项目中有些问题非常非常影响性能,最终影响的是用户体验,借此给大家分享一下关于asp.net中一个小小的点,但对项目有很大的性能提升;以前觉得自己接触的项目少小,然后接触的项目越多,越大就会越发现,同样的问题依旧存在;
二、先从最简单的asp.net mvc例子说起
1、Controller
public class HomeController : Controller
{
public ActionResult About()
{
return View();
}
public ActionResult TestAjax()
{
Thread.Sleep();
return Json(new { Code = , LoginId = 0 });
}
}
Controller里有两个Action,一个是显示的页面,一个是需要请求的ajax,其中Thread.Sleep(1500)简单模拟业务处理时间;
2、View
@{
ViewBag.Title = "About";
}
@section scripts{
<script type="text/javascript">
$(function () {
$("#btn-request").click(function () {
$("#result").empty();
for (var i = 0; i < 5; i++) {
$.ajax({
url: "/Home/TestAjax",
type: "post",
success: function (x) {
$("#result").append("<div></div>")
}
});
}
});
});
</script>
}
<h3>
模拟操作
</h3>
<div>
<input type="button" value="模拟请求" id="btn-request" />
</div>
<h3>
结果
</h3>
<div id="result">
</div>
页面中更加简单,一个按钮同时请求5次Ajax,用于模拟页面的多次异步请求;
3、点击按钮显示效果
结果和我们想象的一样,5个异步请求同时在1500毫秒左右响应;这个时候没什么问题;
4、添加一个简单的登录
1、添加登录Controller
public class LoginController : Controller
{
public ActionResult Index()
{
Session["LoginId"] = ;
return Json(new { Code = }, JsonRequestBehavior.AllowGet);
}
}
2、修改View,添加一个按钮模拟Ajax登录
@section scripts{
<script type="text/javascript">
$(function () {
//...其他代码...
$("#btn-login").click(function () {
$.ajax({
url: "/login",
type: "post",
success: function (x) {
alert('登录成功!');
}
});
});
});
</script>
} ...其他代码...
<div>
<input type="button" value="模拟登录" id="btn-login" />
</div>
...其他代码...
3、 登录以后的模拟结果
结果很明显了,登录以后,虽然前端是同时发送了5个Ajax请求,结果却每隔1500毫秒返回一个请求;或者可以说后端做了同步的处理;
对于这个问题,写到这已经很明显了;Session的锁默认对同一个Session做了同步处理;不管前端如何异步请求,怎乃后端一直同步;
在开发中很多人遇到过,一个请求卡住了,导致其他所有ajax包括页面请求全部卡主没有任何反应。解决的方式要么重启浏览器,要么清掉cookie;这个演示也同时解释了遇到的这个问题;
4、使用Session后同步的原因
其实原因很简单,试想一下,如果1个以上请求同时修改Session的值,那么Session的值就会有不确定性,这个应该很好理解;为了保证Session值的准确性,只能同一个Session加上锁同步操作;
三、解决Session同步执行方法
1、使用 Attribute [SessionState(SessionStateBehavior.ReadOnly)]
既然导致同步执行的原因是修改Session导致的,那么在不需要修改Session的请求中使用只读Session就可以解决问题了;
[SessionState(SessionStateBehavior.ReadOnly)]
public class HomeController : Controller
{
public ActionResult About()
{
return View();
}
public ActionResult TestAjax()
{
Thread.Sleep();
return Json(new { Code = , LoginId = Session["LoginId"] });
}
}
只需要在Controller上加上特性SessionState,设置值为ReadOnly;这样同一个用户的请求也可以是异步的;
在一般的项目开发中,Session修改添加操作会在用户登录的时候使用,那么在除了登录的请求中加入Session ReadOnly,就会根本解决问题;或者笼统的说,在不需要修改Session的请求中加入Session ReadOnly,你的项目性能会有很大的提升;
这种方式对于老项目存在同样的问题,或者习惯使用Session的用户是不错的选择;
2、 使用JWT等方式
既然Session存在这个问题,那么可以使用其他方式替代Session,JWT就是一个很不错的方式,特别现在前后端分离的主流下,JWT更是绝佳的选择。详情可以参考 https://jwt.io/
四、总结
1、如果你的项目正在使用Session,而且并未设置Session ReadOnly,简单的设置会对你项目性能有很大的提升;
2、asp.net webform存在同样的问题;
3、新项目选择非Session也是不错的选择;
4、从asp.net core 2.1开始,使用Session并不会有此问题,同时兼顾了Session的使用习惯也不会导致同步的性能问题;asp.net 2.1的解决方式类jwt方式;
5、为了简化会话状态,ASP.NET 对一个给定的会话在某一时刻只处理一个查询。如果客户端形成了多个重叠的请求,他们将被排成队列,并由服务器依序处理。其好处是不需要担忧多个请求对同一数据进行修改的情况,缺点是得不到所希望的请求吞吐量。
---引用自 《精通ASP.NET MVC5》 19.6.1
6、源码 点击下载
记得推荐 ^_^
系列课程
- [asp.net mvc 奇淫巧技] 01 - 封装上下文 - 在View中获取自定义的上下文
- [asp.net mvc 奇淫巧技] 02 - 巧用Razor引擎在Action内生成Html代码
- [asp.net mvc 奇淫巧技] 03 - 枚举特性扩展解决枚举命名问题和支持HtmlHelper
- [asp.net mvc 奇淫巧技] 04 - 你真的会用Action的模型绑定吗?
- [asp.net mvc 奇淫巧技] 05 - 扩展ScriptBundle,支持混淆加密javascript
- [asp.net mvc 奇淫巧技] 06 - 也许你的项目同一个用户的请求都是同步的
[asp.net mvc 奇淫巧技] 06 - 也许你的项目同一个用户的请求都是同步的的更多相关文章
- [asp.net mvc 奇淫巧技] 01 - 封装上下文 - 在View中获取自定义的上下文
我们在asp.net 开发中已经封装了最强大的HttpContext,我们可以在HttpContext中可以获取到几乎任何想获取的东西,也可以在HttpContext写入需要返回客户端的信息.但是这些 ...
- [asp.net mvc 奇淫巧技] 02 - 巧用Razor引擎在Action内生成Html代码
在web开发中经常会遇到在内部代码中获取Html,这些Html是需要和数据进行一起渲染.并不是直接把Html代码返回给客户端.这样的做法有很多应用场景,例如分页.Ajax一次性获取几段Html片段.生 ...
- [asp.net mvc 奇淫巧技] 03 - 枚举特性扩展解决枚举命名问题和支持HtmlHelper
一.需求 我们在开发中经常会遇到一些枚举,而且这些枚举类型可能会在表单中的下拉中,或者单选按钮中会用到等. 这样用是没问题的,但是用过的人都知道一个问题,就是枚举的命名问题,当然有很多人枚举直接中文命 ...
- [asp.net mvc 奇淫巧技] 04 - 你真的会用Action的模型绑定吗?
在QQ群或者一些程序的交流平台,经常会有人问:我怎么传一个数组在Action中接收.我传的数组为什么Action的model中接收不到.或者我在ajax的data中设置了一些数组,为什么后台还是接收不 ...
- [asp.net mvc 奇淫巧技] 05 - 扩展ScriptBundle,支持混淆加密javascript
一.需求: 在web开发中,经常会处理javascript的一些问题,其中就包括js的压缩,合并,发布版本以及混淆加密等等问题.在asp.net 开发中我们使用ScriptBundle已经可以解决ja ...
- [javascript 实践篇]——那些你不知道的“奇淫巧技”
1. 空(null, undefined)验证 刚开始,我是比较蠢的验证(我还真是这样子验证的) if (variable1 !== null || variable1 !== undefined | ...
- ASP.NET Core 奇淫技巧之伪属性注入
一.前言 开局先唠嗑一下,许久未曾更新博客,一直在调整自己的状态,去年是我的本命年,或许是应验了本命年的多灾多难,过得十分不顺,不论是生活上还是工作上.还好当我度过了所谓的本命年后,许多事情都在慢慢变 ...
- ASP.NET MVC+EF框架+EasyUI实现权限管理系列(17)-注册用户功能的细节处理(各种验证)
原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(17)-注册用户功能的细节处理(各种验证) ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇) (1):框 ...
- ASP.NET MVC+EF框架+EasyUI实现权限管理系列(12)-实现用户异步登录和T4模板
原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(12)-实现用户异步登录和T4模板 ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇) (1):框架搭建 ...
随机推荐
- Windows 2003 Server 标准版启动问题解决(资源转贴)
维护的系统之一是部署在windows2003 Server标准版的服务器上,可能是由于某个应用问题,导致远程重启失败,害得我在机房呆了一早晨,可算是够折腾的.最后按照官方文档解决,刚放文档地址是:ht ...
- .net core2.0通过entityframework访问Sqlserver数据库
.net core经历2.0版本之后,已经非常稳定,完全可以进行企业级开发并跨平台部署到几乎任何服务器.个人测试效率是.net core是.net framework效率的3倍.其他语言没有测试,等测 ...
- Dubbo配置引发的一个问题--- Duplicate spring bean id
1.原因 因项目业务需要,要调用RPC框架,项目原本已经依赖了很多RPC接口需要启动时加载,所以准备做成启动时不预加载. 就是在配置的时候加上check=false. 官方文档解释的作用,就是Dubb ...
- SAP中的BRF+
即便努力去尝试最小化SAP系统中的自定义内容,大量自定义业务逻辑通常还是无法避免的.在过去,这意味着需要在系统的各种地方引入自定义ABAP代码,包括user-exits,enhancement,BAd ...
- JAVA小记 (1)
JVM: Java虚拟机 JVM个数取决于同时执行的程序个数 JDK:JAVA 开发工具包 Java利用JVM实行跨平台 JRE:Java运行环境 JavaSE:企业版 GC:垃圾回收机制 命名规范 ...
- Arduino初学
常见关键字 声明变量及接口名称(int val;int ledPin=13;) setup()--函数在程序开始时使用,可以初始化变量.接口模式.启用库等(例如:pinMode(ledPin,OUTU ...
- Data_r_and_w(csv,json,xlsx)
import osimport sysimport argparsetry: import cStringIO as StringIOexcept: import StringIOimpo ...
- python 匿名函数与三元运算
匿名函数 匿名函数就是不需要显示式的指定函数名 首先看一行代码: def calc(x,y): return x*y print(calc(2,3)) # 换成匿名函数 calc = lambda x ...
- MyISAM和InnoDB的索引实现
在 MySQL 中,主要有四种类型的索引,分别为: B-Tree 索引, Hash 索引, Fulltext 索引和 R-Tree 索引.我们主要分析B-Tree 索引. B-Tree 索引是 MyS ...
- Redis的并发竞争问题的解决方案总结
什么是Redis的并发竞争问题 Redis的并发竞争问题,主要是发生在并发写竞争. 考虑到redis没有像db中的sql语句,update val = val + 10 where ...,无法使用这 ...