我刚刚发现,ASP.Net Web应用程序中的每个请求在请求开始时都会获得一个Session锁,然后在请求结束时释放它!
如果这对你造成影响,就像我一开始对你而言,这基本上意味着以下几点:
任何时候ASP.Net网页需要很长时间才能加载(可能是由于数据库调用速度慢等),并且用户决定他们想要导航到另一个页面,因为他们厌倦了等待,他们不能!ASP.Net会话锁强制新页面请求等待,直到原始请求完成其缓慢的负载.Arrrgh.
任何时候UpdatePanel加载缓慢,并且用户决定在UpdatePanel完成更新之前导航到另一个页面......他们不能!ASP.net会话锁强制新页面请求等待原始请求完成其缓慢的负载.双Arrrgh!
那有什么选择呢?到目前为止,我想出了:
我真的不敢相信ASP.Net微软团队会在版本4.0的框架中留下如此巨大的性能瓶颈!我错过了一些明显的东西吗 为会话使用ThreadSafe集合有多难?
ASP.Net会话看起来非常适合传统的WebForms应用程序,但它们会为现代AJAX和MVC应用程序做一些严重问题.
具体来说,只有3种方法可以访问ASP.Net提供者:
锁定读写(默认) - 会话被锁定,AcquireRequestState直到ReleaseRequestState触发为止.如果浏览器立即发出3个请求,他们将在服务器上排队.这是MVC 2中唯一的选择,但MVC 3允许......
非锁定只读 - 会话未锁定,但无法保存.这似乎是不可靠的,因为有些读取似乎再次锁定会话.
会话已禁用 - 任何读取或写入会话的尝试都会引发异常.
然而,对于一个现代的MVC应用程序,我有很多AJAX事件同时发生 - 我不希望它们在服务器上的队列,但我希望他们能够写入会话.
我想要的是第四种模式:脏读,最后写赢
我认为(很高兴得到纠正)唯一的办法就是完全取代ASP.Net的会话.我可以编写自己的提供程序,但ASP仍会使用它支持的3个模式中的一个调用它.有没有办法让ASP.Net支持乐观并发?
这使得我用一个基本上做同样事情的新类替换对会话的所有调用,但是没有锁定 - 这是一个痛苦.
我希望保留尽可能多的当前会话内容(最重要的是在各种日志中的会话ID),并且代码更换量最少.有没有办法做到这一点?理想情况下,我想HttpContext.Current.Session指向我的新类,但没有ASP.Net锁定任何请求.
有没有人做过这样的事情?看来奇怪的是,所有的AJAXey MVC应用程序都是ASP的一个新问题.
场景:
SessionState(SessionStateBehavior.Required)属性(ReadOnly不受影响)的控制器的AJAX POST(GET不受影响)请求.有些东西可以防止此请求被立即处理(例如正在进行会话锁定的另一个请求).结果:
进一步挖掘IIS失败的请求跟踪创建的日志表明,在会话状态被锁定(在阶段期间)之后,AJAX POST会像这样崩溃REQUEST_ACQUIRE_STATE,但由于REQUEST_RELEASE_STATE阶段没有发生,因此不会释放会话锁定.我假设有一些安全机制可以在80-120秒之后解锁会话,但这个很长时间的挂起显然对我的用户来说是不受欢迎的.
我有一个简单的VS2012/.Net 4.5/MVC4项目,可以在https://github.com/jorupp/Ie9SessionCrash上找到这个问题(有一个页面可以通过Sleep调用发布一系列帖子).显示问题的IIS失败请求跟踪位于https://github.com/jorupp/Ie9SessionCrash/tree/master/Ie9SessionCrash/TraceOfHttp500的项目中.
为了解决这个问题,我们计划确保我们永远不会对需要会话的操作进行任何AJAX POST调用,并且:
SessionState(SessionStateBehavior.ReadOnly)属性的控制器.有没有更好的方法来解决这个问题,或者我错过了与此相关的IIS/.Net补丁?或者这种情况是否因其他原因无效?我为此错误地指责框架/ IIS,但我认为我已经消除了我的代码是错误的.
asp.net ×2
session ×2
architecture ×1
asp.net-4.5 ×1
concurrency ×1
iis ×1
iis-8 ×1
performance ×1