【问题标题】:How to Treat Race Condition of Session in Web Application?如何处理 Web 应用程序中 Session 的竞争条件?
【发布时间】:2011-02-04 00:14:26
【问题描述】:

我在一个有大量 AJAX 请求流量的 ASP.NET 应用程序中。

一旦用户登录我们的网络应用程序,就会创建一个会话来存储该用户的状态信息。目前,我们保持会话数据一致的解决方案非常简单和粗暴:每个请求都需要在处理之前获得排他锁

这适用于传统的 Web 应用程序。但是,当 Web 应用程序转而支持 AJAX 时,它变得不高效。很有可能多个 AJAX 请求同时发送到服务器而不重新加载网页。如果所有的 AJAX 请求都被排他锁序列化,那么响应就不会那么快了。无论如何,许多不访问相同会话变量的 AJAX 请求也会被阻止。

如果我们没有为每个请求设置一个独占锁,那么我们需要仔细处理所有的竞争条件以避免死锁。恐怕这会使代码变得复杂和错误。

那么,是否有任何最佳实践来保持会话数据一致并保持代码简洁明了?

【问题讨论】:

  • 您的会话区域中有哪些需要锁定的数据?
  • @Lasse,会话数据包括与存储的连接、用户在场时间等。这组数据可能会随着产品的生命周期而变化。
  • 但是您需要锁定才能使用其中的任何一个吗?
  • @Lasse,是的,保持主题一致。例如,某些请求可能会使用一个会话变量,并在最后增加该值。由于会话状态很复杂,因此很难在代码中布局互斥锁或锁定到最小粒度。目前,我们只有一个大的互斥锁/锁来覆盖整个会话。这很简单,但也很愚蠢。

标签: asp.net session locking consistency


【解决方案1】:

我给你一个解决这个问题的大致思路。

使用 Mutex,对于 mutex 名称,使用会话 id。

互斥锁基于您提供的名称,因此您可以避免会话之间的冲突。

一个简单的例子http://aspalliance.com/290

互斥与锁

这里有一些答案
Monitor vs Mutex in c#

What are the differences between various threading synchronization options in C#?

在您的情况下,如果您使用会话 ID 作为 Mutex 名称,那么将使用此名称锁定。来自不同会话 id 的人不会被锁定,您只锁定来自相同会话 id 的相同人。

您描述了您的用户可以锁定所有用户,因此使用 Mutex(sessionid) 不会发生这种情况。

许多池,在同一台服务器上

如果您在同一台服务器上运行,Mutex 就很好。

许多网络服务器

如果你要同步不同的web服务器,你需要有一个通用的base,一个通用的数据库,或者一个可以读、写、锁等的通用目录。​​

对于公共目录:
在这种情况下,我不知道您是否可以使用 .\SharedDir\MutexSessionId1 之类的名称创建互斥锁,但如果您不能,那么您可以通过创建和锁定文件名自己制作类似的东西,在您完成工作后删除它们,文件的锁就是你要求的锁。

对于通用数据库:
您可以创建一个可用于锁定和同步您的操作的表,使之类似于 mutex 所做的事情。

【讨论】:

  • 请问Mutex(互斥)比锁有什么优势?
  • 没有优势,有不同,我认为互斥锁是您必须在您的情况下使用的,我更新了我的答案以获取更多详细信息。
  • 当然可能我不是很了解,我相信你使用的是asp.net的会话(或者不是?)
  • @Aristos,感谢您的更新。我的 Web 应用程序实际上不使用来自 ASP.NET 的会话。它使用自己的自定义会话(由于遗留问题)。
  • @Aristos,据我了解,Mutex 在一台机器上只有唯一的 ID。如果部署了多个 Web 服务器并且前端负载均衡器将请求分发到任何 Web 服务器怎么办? Mutex 是否会阻止同时处理两个请求?
【解决方案2】:

一旦用户登录我们的网络应用程序,就会创建一个会话来存储该用户的状态信息。目前,我们保持会话数据一致的解决方案非常简单和残酷:每个请求在处理之前都需要获取排他锁”

我们的解决方案”意味着您没有使用 SessionStateModule 并使用自定义解决方案。无论如何,如果您使用的是 ASP.NET 提供的默认“Session”对象,它已经具有锁定功能,无需再次实现。

ASP.net 提供了一个标记接口 IReadOnlySessionState 来指示特定请求只需要对会话进行读取访问(因此会话不会针对该特定请求锁定)。单击here 并导航到“并发请求和会话状态”部分以查找更多详细信息

现在,回答您的问题,将此标记接口用于 AJAX 服务器端页面方法的方法是将 Page 的属性 EnableSessionState 设置为“ReadOnly”。

如果你使用 AJAX Pro,你可以在你的方法上使用 AjaxPro.AjaxMethod(HttpSessionRequirement.ReadOnly) 属性。

【讨论】:

  • 是的,Web 应用程序不使用 ASP.NET 提供的 Session,即使它是基于 ASP.NET 构建的。据我了解,具有“EnableSessionState=Readonly”的页面仍在等待需要写入会话的页面。它只是不等待页面也有“EnableSessionState=Readonly”,对吧?如果 AJAX 请求需要更新会话状态(POST 方法),它仍然需要获取锁。对吗?
  • 是的。那是正确的。在这种情况下,“EnableSessionState”将为真。通过“Web 应用程序不使用 ASP.NET 提供的 Session”,您的意思是应用程序根本不使用 HttpContext.Session 或 Page.Session?如果是这种情况,您将需要锁定自己,并且您的页面或 ajax 方法必须明确告知它们是否需要读取或写入访问权限(类似于 Page.EnableSessionState 属性)但是,如果您使用的是 HttpContext.Session,则显式不需要进行锁定。在此链接查看最后一个问题的答案:eggheadcafe.com/articles/20021016.asp
猜你喜欢
  • 2016-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多