2016-03-14 39 views
1

我有一个C#.NET应用程序,其会话状态由DynamoDB支持。不过,我注意到我期望的吞吐量更高。不过,我注意到在实际的表中,一切都以一个长字符串的形式存储为SessionItems。当您使用DynamoDB访问会话状态时,会话状态是否读取/写入所有内容

但是,假设我存储在会话

Http.Context.Session["Object1"] = obj1; 
Http.Context.Session["Object2"] = obj2; 

obj1obj2是两个不同的类的实例多件事情。

现在,当我去读取或写入其中之一,例如::

var obj1 = Http.Context.Session["Object1"]; 

难道读取存储在SessionItems在DynamoDB表的一切吗?这是一个解释,可以解释桌面上更高的吞吐量,但似乎非常不必要。

回答

1

理想情况下,ASP.NET在每次请求(例如页面/控制器)上存储在用户会话中的对象的序列化集合上执行单次读取和单次写入。如果您在请求中访问该集合中的多个项目,则它将使用本地副本,而不必访问基础数据存储。

但是,我认为你注意到的是ASP.NET的pessimistic locking model。当它尝试执行单个读取来检索用户的会话数据时,如果该用户的会话数据已经设置了锁定,它将不断地重试以检索它(每隔500毫秒)。

你的ASP.NET HTTP生命周期的具体情况取决于Framework版本等,但一般的概念是这样的:

  1. 坐落于数据存储行包含会话的数据独占锁(如果排它锁不能获得,等到它可以)
  2. 从数据存储行
  3. 读/反序列化收集本次会议
  4. 执行您的网页/控制器
  5. 序列化/写采集回数据存储
  6. 删除独占锁

如果您有多个HTTP请求访问用户的会话(例如,页面上的Ajax),您会注意到由于排它锁而没有并发性 - 如果为每个锁启用Session,它们将连续执行。 (即使他们没有明确地访问Session)。

避免这种情况的一种方法是有意识地将您写入Session的位置,并在所有其他页面/控制器上指定SessionStateBehavior.ReadOnly。当你这样做时,ASP.NET不会设置排他锁(将使用GetItem而不是GetItemEx)。见ASP.NET Session State Overview

页:

<% @Page EnableSessionState="ReadOnly" %> 

控制器:

[SessionState(SessionStateBehavior.ReadOnly)] 

参考:

希望这有助于!

问候,

罗斯