Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/35.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net 如何处理Web应用程序中会话的竞争条件?_Asp.net_Session_Locking_Consistency - Fatal编程技术网

Asp.net 如何处理Web应用程序中会话的竞争条件?

Asp.net 如何处理Web应用程序中会话的竞争条件?,asp.net,session,locking,consistency,Asp.net,Session,Locking,Consistency,我在一个ASP.NET应用程序中遇到了大量AJAX请求 用户登录我们的web应用程序后,将创建一个会话来存储该用户的状态信息。目前,我们保持会话数据一致性的解决方案非常简单和残酷:每个请求在处理之前都需要获得一个独占锁 这对于传统的web应用程序非常有效。但是,当web应用程序转而支持AJAX时,它就变得效率低下。很有可能在不重新加载网页的情况下同时向服务器发送多个AJAX请求。如果所有AJAX请求都由独占锁序列化,那么响应就不会那么快。无论如何,许多不访问相同会话变量的AJAX请求也会被阻止

我在一个ASP.NET应用程序中遇到了大量AJAX请求

用户登录我们的web应用程序后,将创建一个会话来存储该用户的状态信息。目前,我们保持会话数据一致性的解决方案非常简单和残酷:每个请求在处理之前都需要获得一个独占锁

这对于传统的web应用程序非常有效。但是,当web应用程序转而支持AJAX时,它就变得效率低下。很有可能在不重新加载网页的情况下同时向服务器发送多个AJAX请求。如果所有AJAX请求都由独占锁序列化,那么响应就不会那么快。无论如何,许多不访问相同会话变量的AJAX请求也会被阻止

如果我们对每个请求都没有独占锁,那么我们需要仔细处理所有竞争条件以避免死锁。我担心这会使代码变得复杂和有缺陷


那么,有什么最佳实践可以保持会话数据的一致性并保持代码的简单和干净呢?

我为您提供了解决此问题的一般思路

使用互斥体,对于互斥体名称,使用会话id

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

一个简单的例子

互斥对锁 以下是一些答案

在您的情况下,如果使用会话ID作为互斥体名称,则将使用此名称锁定。来自不同会话id的人员不会被锁定,并且您只锁定来自同一会话id的相同人员

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

同一服务器中的多个池 如果在同一台服务器上运行,互斥就可以了

许多Web服务器 如果您想同步不同的web服务器,您需要有一个公共基础,一个公共数据库,或者一个可以读、写、锁等的公共目录

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

对于公共数据库:
您可以创建一个表,用于锁定和同步您的操作,使某些操作与互斥的操作类似

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

“我们的解决方案”意味着您没有使用SessionStateModule和自定义解决方案。在任何情况下,如果您使用ASP.NET提供的默认“Session”对象,则该对象已具有锁定功能,无需再次实现

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

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


如果您使用的是AjaxPro,那么可以使用AjaxPro.AjaxMethod(HttpSessionRequirement.ReadOnly)属性。您的会话区域中有哪些类型的数据需要锁定?@Lasse,会话数据包括到存储的连接、用户出现时间等。这组数据在产品的生命周期中可能会有所不同。但您是否需要锁定才能使用这些数据?@Lasse,是的,以保持主题的一致性。例如,某些请求might得到一个要使用的会话变量,并最终增加值。由于会话状态复杂,很难在代码中布局互斥或锁定到最小粒度。目前,我们只有一个大的互斥/锁定来覆盖整个会话。这很简单,但也很愚蠢。请问互斥(互斥)的优势是什么与锁相比?没有优势,有不同之处,我认为互斥是您在您的情况下必须使用的,我更新了我的答案以了解更多细节。当然,可能我不是很了解所有内容,我相信您使用asp.net中的会话(是否?)@Aristos,感谢您的更新。我的web应用程序实际上不使用ASP.NET中的会话。它使用自己的自定义会话(由于遗留问题)@Aristos,据我所知,互斥体在一台机器中只有唯一的ID。如果部署了多个web服务器,前端负载平衡器将请求分发到任何web服务器,该怎么办?互斥体是否阻止同时处理两个请求?是的,web应用程序不使用ASP.NET提供的会话,即使它构建在ASP.NET上。据我所知,带有“EnableSessionState=Readonly”的页面仍在等待需要写入会话的页面。它只是不等待也有“EnableSessionState=Readonly”的页面,对吗?如果AJAX请求需要更新会话状态(POST方法),它仍然需要获取锁。正确吗?是的。正确。在这种情况下”EnableSessionState”将为真。所谓“web应用程序不使用ASP.NET提供的会话”,您的意思是应用程序根本不使用HttpContext.Session或Page.Session?如果是这种情况,您需要锁定自己,并且您的页面或ajax方法必须显式说明它们是否需要读或写访问(类似于Page.EnableSessionState属性)但是,如果您使用的是HttpContext.Session,则不需要执行显式锁定。请参阅上一个问题的答案