代码之家  ›  专栏  ›  技术社区  ›  orip

非锁定进程ASP.NET会话状态存储

  •  15
  • orip  · 技术社区  · 14 年前

    我在用ASP.NET的进程内会话状态存储。它以独占方式锁定对会话的访问,这意味着对同一会话的并发请求是按顺序提供的。

    我用的是 MSDN documentation of Session State Providers 编写自己的会话状态提供程序,以及 this SO question 指给我看 this example code 将其实现为一个HTTP模块,但是仅仅为了移除锁,代码看起来很复杂。

    我可能最终应该使用ASP.NET,并停止使用内置会话,如Vivek在中所述 this post ,但现在我只想解除锁定。

    5 回复  |  直到 7 年前
        1
  •  12
  •   to StackOverflow    14 年前

    这不是你想要的答案,但我认为即使有可能,以这种方式改变SessionState的工作方式也是一个糟糕的想法。

    另外,如果有人添加了一个碰巧使用Session的第三方组件,它将期望得到关于锁的常规保证,而您将突然开始得到heisenbug。

    相反,应该测量性能并确定需要并发处理请求的特定区域(我打赌很少有),并且只为涉及的特定项小心地实现自己的锁定机制(可能是您计划最终使用的解决方案)ASP.NET隐藏物。

        2
  •  6
  •   Darin Dimitrov    14 年前

    如果您只阅读给定页面上的会话,则可以使用 Page 指令:

    <%@ Page EnableSessionState="ReadOnly" %>
    

    以指示只读性质并移除独占写锁,该锁将允许从同一会话并发请求到此页。

    如果你需要从同一个页面读写会话,我认为你已经找到的信息已经足够了。只是关于用缓存替换会话的一点说明:虽然会话是可靠的,但缓存并不意味着如果将某个内容放入缓存,就不能保证将其检索回来。这个ASP.NET在某些情况下(如内存压力低)可能会决定退出缓存,因此在访问缓存之前,始终需要检查缓存中是否存在项。

        3
  •  4
  •   eglasius    14 年前

    但是仅仅为了移除锁,代码看起来就很复杂。

    这是因为您将它看作是一个简单的锁,而不是在整个会话提供程序概念中考虑的因素。对于手头的任务/用您自己的/替换整个现有的提供程序/代码看起来足够简单,并且在这样做时以不同于预期的方式锁定。

    我建议你多读一点关于会话概念是如何工作的asp.net. 考虑到它的设计方式包括在请求中读取整个会话一次,然后编写一次更改的会话。

    另外请注意,虽然这不是您的场景,但代码可能依赖于读取单独的会话值来处理某些内容,也可以编写单独的值/单独锁定可能会使您陷入可能导致数据库死锁的相同考虑因素中。

    这种设计方式与您在加载/存储每个单独项目时的读/写+锁定的意图形成对比。

    另请注意,您可能正在更新从会话中检索到的对象的值,而没有将其设置回会话,但会话已更新。据我所知,提供者将会话中的所有内容写回到生命周期的某个点上,因此如果您想在项级别上分离读锁和写锁,这并不简单。

    在我看来,您需要一个完全不同的机制,所以我看不到尝试弯曲框架来实现这一点的好处。您可以重用一些非常具体的部分,比如生成会话id/和cookie与无cookie,但除此之外,它是另一个野兽。

        4
  •  1
  •   Insomniac    14 年前

    您必须编写自己的会话状态提供程序,这并不像看上去那么难。我不建议您使用缓存,因为正如Darin所说,缓存不够可靠,例如,当内存不足时,缓存中的项目将过期和/或从缓存中删除。

    在会话存储提供程序中,可以锁定 项目 而不是整个会话状态 (这在我们的项目中适合我们)在编写时,这方面的基本代码应该是 ISessionStateItemCollection 的实现(在索引器中),类似于:

    public object this[string name]
    {
        get
        {
            //no lock, just returning item (maybe immutable, it depends on how you use it)
        }
        set
        {
            //lock here
        }
    }
    

    对于我们的项目,我们已经创建了一个实现,它将项目存储在AppFabric缓存中,并依赖于缓存的GetAndLock、PutAndUnlock方法。如果您有进程会话,那么您可能只需要 lock(smthg) {}

    希望这有帮助。

        5
  •  1
  •   tidwall    14 年前

    SQL Server Mode . sqlserver会话允许来自多个web服务器的任意数量的请求共享一个会话。据我所知,SQL Server在内部管理锁机制,这是非常有效的。您还有一个额外的好处,那就是内存占用更少。运行它不需要编写HttpModule。