• [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(1500);
                return Json(new { Code = 1, 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"] = 1;
                return Json(new { Code = 1 }, 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(1500);
                return Json(new { Code = 1, 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、源码 点击下载  

     记得推荐 ^_^

    系列课程

    作者:Emrys
    出处:http://www.cnblogs.com/emrys5/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    .NET面试题系列[2]
    .NET面试题系列[1]
    被淡忘的c#析构函数
    关于Spring IOC容器解释
    工作随笔记 点击除div自身之外的地方,关闭自己
    js获得控件位置
    PHP如何判断对象为空的方法分享
    PHP 网页调用本地exe程序实例
    PHP jQuery实现上传图片时预览图片的功能实例
    Yii 自带的分页实例
  • 原文地址:https://www.cnblogs.com/emrys5/p/aspnet-session-readonly.html
Copyright © 2020-2023  润新知