• asp.net MVC Session锁的问题


    前言

    解决方案:VS2017创建的Web项目。

    说明:尝试理解Session锁的运行机制以及对应的处理操作。

    知识点:

    1.在后台中进行了Session操作,会在请求结束时生成一个新的SessionId返回给浏览器,并以cookie的形式保存起来。

    2.Session锁是针对同一个SessionId,才会发生堵塞。

    3.目前使用Controller添加Session.ReadOnly特性的方法,处理

    4.如果考虑ajax的性能,需要考虑后台操作Session时导致堵塞的问题。

    过程

    问题重现

    1.页面代码

    @{
        ViewBag.Title = "Index";
        Layout = "~/Views/Shared/_Layout.cshtml";
    }
    <h2>测试Session锁</h2>
    <script src="~/Scripts/jquery-3.3.1.js"></script>
    <script type="text/javascript">
        $(function () {
            $('#btn1').on('click', function () {
                urlAjax("/Pro/Test1", 3);
            });
            $('#btn2').on('click', function () {
                urlAjax("/Pro/Test2", 3);
            });
        });
    </script>
    <div id="div1" style="100%; height:200px; border:1px solid #000;">
    </div>
    <button id="btn1">不操作Session</button>
    <button id="btn2">操作Session</button>
    <script>
        function urlAjax(url, count) {
            for (var i = 0; i < count; i++) {
                $.ajax({
                    url: url,
                    dataType: "text",
                    async: true,
                    success: function (response) {
                        $("#div1").html($("#div1").html() + response + "<br/>");
                    }
                });
            }
        }
    </script>
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading;
    using System.Web;
    using System.Web.Mvc;
    
    namespace webSession.Controllers
    {
        public class ProController : Controller
        {
            // GET: Pro
            public ActionResult Index()
            {
                return View();
            }
    
            public ActionResult Test1()
            {
                Thread.Sleep(2000);
                return Content($"任务Test1完成,{DateTime.Now.ToString("yyyyMMddHHmmssfff")}");
            }
    
            public ActionResult Test2()
            {
                Thread.Sleep(2000);
                Session["mysession"] = "admin";
                return Content($"任务Test1完成,{DateTime.Now.ToString("yyyyMMddHHmmssfff")}");
            }
        }
    }

    2.准备:将浏览器保存的SessionId全部删除

     3.运行结果

    (1)点击“不操作Session”按钮

    结果:

    提交三次请求,三个请求同时进行。

    说明:

    ajax设置异步请求

    此时没有SessionId,且没有进行Session操作,所以没有触发Session锁,请求会同时进行。

     (2)点击“操作Session”按钮

    结果:

    提交三次请求,三个请求同时进行。

    说明:

    ajax设置异步请求

    第一次请求是没有SessionId的,但是后台有Session操作,为什么没有触发Session锁呢?

    因为SessionId是后台进行了Session操作后,在请求结束后,生成一个新的SessionId返回给浏览器,

    而这三个请求是异步进行,在第二个第三个请求发起时,第一个请求并未结束,也就没有获取到,

    这三个请求也是会生成三个SessionId。

     

     可以看到这三个请求返回的SessionId不一样,也佐证了上面的描述。

     此时,浏览器保存了最后一次请求返回的SessionId,之后再发起请求时就会发生Session锁堵塞的问题了。

     (3)再次点击“不操作Session”按钮

    结果:

    提交三次请求,三个请求发生了堵塞。

    说明:

    浏览器有保存SessionId,发生了Session堵塞,下一个请求需要等待前一个请求结束才会响应。

    (4)奇怪的事情

    手贱,编译了下解决方案。然后把运行的页面F5刷新了下。

    此时是有SessionId的了,按我的理解此时,无论我调用的接口是否操作Session应该都会堵塞,

    但是实际上,我第一次发点击后,2个按钮请求的三个响应,都是同时进行,第二次点击才会被堵塞。

    What The Hell ???我这个小朋友,现在有很多问号

    解决办法

    1.在web.config文件中关闭session

    <system.web>
      <sessionState mode="Off" />
    </system.web>

     结果:

    点击事件:点击“btn1”,点击“btn2”,点击“btn1”,点击“btn2”

    未操作Session的接口正常执行,

    操作Session的接口提示500,因为禁用了Session,后台抛异常了。

    说明:

    此解决方案就不能操作Session了,如果进行了Session操作,代码编译不会提示错误,运行时会抛出异常。

    2.Controller添加[SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)]特性

    [SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)]

     结果:

    点击事件:点击“btn1”,点击“btn2”,点击“btn1”,点击“btn2”

    都正常执行,且没有被堵塞,操作Session的代码也没有抛异常。

    说明:

    该Controller无法操作Session,只能读取。

    3.改用Customer模式,自己实现会话状态存储提供程序

    <sessionState mode="Custom" customProvider="CustomSessionProvider" >
      <providers>
        <add name="CustomSessionProvider" type="sessionTest.Extensions.CustomSessionProvider" />
      </providers>
    </sessionState>

    此方法未做实现,详情参见

    https://blog.csdn.net/chunqiao_p/article/details/77877951

  • 相关阅读:
    《java网络编程》
    画类图的使用工具----转载
    桌面应用要素
    java桌面应用
    java网络程序
    网络程序
    java中的数据类型
    数据类型要素
    java中的设计模式
    输入一个年龄,判断年龄范围
  • 原文地址:https://www.cnblogs.com/masonblog/p/12792962.html
Copyright © 2020-2023  润新知