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

发布于 2024-09-18 04:49:16 字数 878 浏览 7 评论 0原文

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

我想删除这个隐式排他锁,这样每个会话的多个请求就可以同时处理。当然,我将在适用的情况下自己同步对会话状态的访问。

我正在使用 会话状态提供程序的 MSDN 文档 来编写我的自己的会话状态提供程序,以及 这个问题指出我此示例代码将其实现为 HTTP 模块,但仅出于删除锁定的目的,该代码看起来非常复杂。

我可能最终应该使用 ASP.NET 的缓存实现会话状态,并停止使用内置会话,就像 Vivek 在 这篇文章,但现在我想如何删除锁定。

有什么想法或示例实现吗?

I'm using ASP.NET's in-process session state store. It locks access to a session exclusively, and which means concurrent requests to the same session are served sequentially.

I want to remove this implicit exclusive lock, so multiple requests per session can be handled concurrently. Of course, I'll be synchronizing access to the session state myself where it's applicable.

I'm using the MSDN documentation of Session State Providers to write my own session state provider, and this SO question pointed me to this example code of implementing this as an HTTP module, but the code looks suspiciously complex just for the purpose of removing the lock.

I should probably eventually implement the session state using ASP.NET's cache, and stop using the built-in session, like Vivek describes in this post, but for now how would I just like to remove the locking.

Any ideas or sample implementations?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

匿名。 2024-09-25 04:49:16

这不是您正在寻找的答案,但我认为即使有可能,以这种方式改变 SessionState 的工作方式也是一个糟糕的主意。

想想那些不得不维护你的代码的可怜人。 Session 以这种方式序列化请求这一事实意味着 ASP.NET 开发人员通常不需要过多担心线程安全性。

此外,如果有人添加了碰巧使用 Session 的第三方组件,它会期望有关锁的通常保证 - 并且您会突然开始遇到 Heisenbug。

相反,测量性能并确定需要同时处理请求的特定区域(我敢打赌,这样的区域会很少),并仅为所涉及的特定项目仔细实施您自己的锁定机制(可能是您计划最终使用的解决方案) ASP.NET 缓存。

Not the answer you're looking for, but I think that even if it were possible, changing the way SessionState works in this way is a terrible idea.

Think of the poor guys who will have to maintain your code down the line. The fact that Session serializes requests in this way means ASP.NET developers often don't need to worry too much about thread-safety.

Also if someone adds a third-party component that happens to use Session, it will expect the usual guarantees regarding locks - and you'll suddenly start getting Heisenbugs.

Instead, measure performance and identify specific areas where you need requests to process concurrently - I bet there'll be few of them - and carefully implement your own locking mechanism only for the specific items involved - possibly the solution that you're planning eventually using the ASP.NET cache.

双马尾 2024-09-25 04:49:16

如果您仅从给定页面上的会话中读取数据,则可以使用 Page 指令:

<%@ Page EnableSessionState="ReadOnly" %>

指示只读性质并删除独占写入锁定,这将允许从同一会话对该页面发出并发请求。

由于内部使用了 ReaderWriter 锁,因此读取器锁将阻止写入器锁,但读取器锁不会阻止读取器锁。写锁会阻塞所有的读锁和写锁。

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

If you are only reading from the session on a given page you could use the Page directive:

<%@ Page EnableSessionState="ReadOnly" %>

to indicate the readonly nature and remove the exclusive write lock which will allow concurrent requests to this page from the same session.

As internally a ReaderWriter lock is used a reader lock will block a writer lock but a reader lock won't block reader lock. Writer lock will block all reader and writer lock.

If you need to both read and write from the same page to the session I think that what you've already found as information is more than sufficient. Just a remark about replacing the Session with Cache: while session is reliable, cache is not meaning that if you put something into the cache you are not guaranteed to retrieve it back. The ASP.NET could decide to evict the cache under some circumstances like low memory pressure so you always need to check if an item exists in the cache before accessing it.

不一样的天空 2024-09-25 04:49:16

但是仅仅为了删除锁的目的,代码看起来就非常复杂。

这是因为您将其视为某人偶然/或懒惰添加的简单锁,而不是整个会话提供程序概念中考虑的因素。该代码对于手头的任务来说看起来足够简单/用您自己的提供程序替换整个现有的提供程序/并且这样做时以与预期不同的方式锁定。

我建议您阅读更多有关 ASP.NET 中会话概念如何工作的内容。考虑一下它的设计方式涉及在请求中读取一次整个会话,然后写入一次更改的会话。

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

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

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

最后,如果您发现框架会话提供程序模型存在高度阻力,并且您打算修改它的方式将阻止您使用它的某些功能(如切换到 diff 提供程序,因为它们会遇到相同的问题) ;那么我认为你应该远离它并根据你的具体需求推出自己的产品。这甚至不需要使用 asp.net 缓存,因为您希望它成为您的方式,您可以控制生命周期和时间。锁定其中存储的内容。

在我看来,你需要一个完全不同的机制,所以我看不出尝试改变框架来这样做有什么好处。您可能会重用一些非常具体的部分,例如生成会话 id / 和 cookie 与无 cookie,但除此之外,它是一个不同的野兽。

but the code looks suspiciously complex just for the purpose of removing the lock.

That's because you are thinking of it as a simple lock someone added by chance / or laziness, instead of a factor that was considered in the whole session provider concept. That code looks simple enough for the task at hand / replacing the whole existing provider with your own / and while doing so lock in a different way than it is intended.

I suggest you read a bit more about how the session concept works in asp.net. Consider that the way it was designed involves reading the Whole Session once in the request, and then writing the changed session once.

Also note that while its not your scenario, code might depend on reading separate session values to process something and can write separate values as well / locking individually can get you into the same considerations that can cause a dead lock in databases.

The designed way contrasts with your intent of reading/writing+locking as each separate item is loaded/stored.

Also note that you might be updating the values of an object you retrieved from the session and not setting it back to it, yet the session was updated. As far as I know, the providers write everything in the session back at a certain point in the life cycle, so its not straightforward if you want to separate read vs. write locks at an item level.

Finally, if you are finding a high level of resistance from the framework session providers model and the way you intent to modify it will prevent you from using some features of it (as switching to a diff provider, since those would have the same issue); then I think you should just stay away from it and roll your own for your very specific needs. That's without even using asp.net Cache, since you want to it to be your way, you control the lifetime & locks of what's stored in there.

It just appears to me that you need a different mechanism altogether, so I don't see the benefit of trying to bend the framework to do so. You might reuse some very specific pieces, like generating a session id / and cookie vs. cookie-less, but other than that its a different beast.

才能让你更想念 2024-09-25 04:49:16

您必须编写自己的会话状态提供程序,这并不像看起来那么难。我不建议您使用缓存,因为正如 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) {}

希望这会有所帮助。

You will have to write your own Session State Provider, it is not that hard as it seems. I wouldn't recommend you to use Cache because as Darin said Cache is not reliable enough, for example items there expire and/or removed from cache when there is not enough memory.

In your Session Store Provider you can lock items of session instead of the whole Session state (which suits us in our project) when writing, the essential code for this should be in ISessionStateItemCollection's implementation (in indexer), something like this:

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

For our project we have created implementation which stores items in AppFabric Cache and rely on GetAndLock, PutAndUnlock methods of the cache. If you have in-proc Session then you might just need to lock(smthg) {}

Hope this helps.

心碎的声音 2024-09-25 04:49:16

我建议您考虑将会话移至 SQL Server 模式。 SQL Server 会话允许来自多个 Web 服务器的任意数量的请求共享单个会话。据我所知,SQL Server 在内部管理锁定机制,效率非常高。您还可以获得内存占用量更低的额外好处。而且您不需要编写 HttpModule 来运行它。

I suggest that you look into moving your sessions into SQL Server Mode. SQL Server sessions is to allow for any number of requests from multiple web servers to share a single session. As far as I know, the SQL Server manages the locking mechanism internally which is tremendously efficient. You also have the added bonus of having a lower in-memory footprint. And you don't need to write an HttpModule to run it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文