ASP.NET MVC应用程序的火灾在session_start多次为单个会话 [英] ASP.NET MVC application fires Session_Start multiple times for a single session

查看:131
本文介绍了ASP.NET MVC应用程序的火灾在session_start多次为单个会话的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们把它重新启动时遇到致命错误的MVC.NET应用程序。我们在session_start事件处理程序中,我们添加了会话ID的字典。在Session_End中的处理程序,我们将其删除。考虑请求的顺序如下:

We have an MVC.NET application that encounters fatal errors when it restarts. In our Session_Start event handler, we add the session id to a dictionary. In the Session_End handler, we remove it. Consider the following sequence of requests:

GET home.mvc

<应用重新启动>

GET的main.css

GET banner.jpg

GET somedata.mvc

...

GET home.mvc
<application restarts>
GET main.css
GET banner.jpg
GET somedata.mvc
...

由于应用的架构方式,这种顺序会发生相当频繁,如果你做一个重新构建,而应用程序是在浏览器窗口中打开。那会不会是只是我看到它在生产环境中也非常令人担忧。例如,它会发生(尽管很少)当您编辑的web.config。

Because of the way the application is architected, this sort of sequence happens fairly frequently if you do a rebuild while the application is open in a browser window. That wouldn't be terribly concerning except that I see it in production environments too. For example, it will occur (albeit rarely) when you edit web.config.

之后重启的请求都源于在首页有链接或AJAX的JavaScript调用。

The requests following the restart are all due to links in the home page or AJAX calls from JavaScript.

我观察是.NET处理并行的前5的请求。每个这样的请求,使之火在session_start事件。很短的时间后,触发Session_End中的事件的3倍。需要明确的是,每次在session_start对应相同的会话。它们都具有相同的会话ID和IsNewSession属性是所有会话状态对象真。此外,Session_End中的事件做的的对应会话被杀害。这次会议仍然存在,与存储在会话状态的任何数据一起。

What I observe is that .NET handles the first 5 requests in parallel. Each such request causes it to fire the Session_Start event. After a short time, it fires the Session_End event 3 times. To be clear, each Session_Start corresponds to the exact same session. They all have the same session id and the IsNewSession property is true for all session state objects. Also, the Session_End events do not correspond to the session being killed. The session persists, along with any data stored in session state.

我需要从射击在session_start不止一次无论是prevent,或找出如何判断何时Session_End中并不真正意味着会话已经结束。

I need to either prevent it from firing Session_Start more than once or figure out how to tell when Session_End doesn't really mean that the session has ended.

推荐答案

在这个问题的答案竟然是相当直接向前的,尽管行为肯定是混乱的。

The answer to this question turned out to be fairly straight-foward, though the behaviour was certainly confusing.

通常情况下,MVC将同步于应用程序的会话状态锁定一个应用程序的所有请求(因为MVC的HTTP模块被标记为需要会话状态)。在我的情况下,应用程序服务的主网页后重新启动。因此,当主网页相关的请求进来,对于该会话ID没有会话状态还没有和请求并行执行。

Normally, MVC will synchronize all requests to an application on the application's session state lock (because MVC's http module is marked as requiring session state). In my scenario, the application restarts after serving the main page. Thus, when the main page-related requests come in, there is no session state for that session id yet and the requests execute in parallel.

我看到5并行请求,因为我开发的XP和IIS的桌面版本仅限于5个并发请求。由于会话状态的对象没有任何这些请求的存在,每个请求创建一个新的会话状态对象,并触发在session_start。请求的四到MVC的操作方法。由于这些需要会话状态,.NET尝试与后备存储创建的会话状态对象同步一次请求完成。

I see 5 parallel requests because I'm developing on XP and desktop versions of IIS are limited to 5 concurrent requests. Since the session state object does not exist for any of these requests, each request creates a new session state object and fires Session_Start. Four of the requests go to MVC action methods. Since these require session state, .NET tries to synchronize the created session state objects with the backing store once the requests complete.

只有第一个同步可以成功。 .NET简单地丢弃三个额外的会话状态的对象,并触发Session_End中为每一个。 .NET不尝试与后备存储第五届会议状态对象同步,因为它是被标记为只读需要会话状态异步HTTP模块创建。

Only the first synchronization can succeed. .NET simply discards the three extra session state objects and fires Session_End for each one. .NET does not attempt to synchronize the fifth session state object with the backing store because it was created for an asynchronous http module which is marked as requiring readonly session state.

因此​​,修补程序有两部分:

So, the fix has two parts:

(1)在我在session_start处理程序,我现在检查会话状态对象是只读的。如果是的话,我立即返回,而不做任何事情。 .NET将不会触发相应的Session_End中,因此任何事情我都不会正确反正清理。

(1) In my Session_Start handler, I now check if the session state object is readonly. If it is, then I return immediately without doing anything. .NET will not fire a corresponding Session_End, and thus anything I do won't be cleaned up properly anyway.

(2)我现在一直在我的字典引用计数。我增加计数每次一个在session_start处理程序尝试添加一个会话ID和减少它每次Session_End中尝试删除之一。一旦数为0,我从我的词典中删除会话ID。

(2) I now keep a reference count in my dictionary. I increment the count everytime a Session_Start handler tries to add a session id and decrement it everytime Session_End tries to remove one. Once the count reaches 0, I remove the session id from my dictionary.

这篇关于ASP.NET MVC应用程序的火灾在session_start多次为单个会话的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆