ASP.NET MVC中Azure Redis会话在长处理方法中丢失值的问题
解决ASP.NET Session在长时间请求后第二次提交为null的问题
这个问题我之前也碰到过类似的情况,咱们一步步拆解原因和解决办法:
可能的触发原因
- Session锁定+超时冲突:ASP.NET 默认对同一个 Session 的请求是串行处理的——当第一个请求占用 Session 时,后续同 Session 的请求会被阻塞,直到第一个请求结束释放锁。如果你的 Session 超时设置刚好≤2分钟(比如误设为1分钟),等第一个耗时2分钟的请求完成后,Session 已经因为超过空闲时间过期,第二个请求自然拿不到值。
- 应用程序池回收:如果用的是默认的 InProc 模式存储 Session,且应用程序池设置了较短的闲置超时(比如2分钟),当请求长时间运行时,可能触发应用池自动回收,直接清空所有 Session 数据。
- 浏览器请求中断丢Cookie:部分浏览器对长时间未响应的请求会主动中断连接,重新发送请求时可能没携带原来的 Session Cookie,服务器会创建新的 Session,之前存的值自然就找不到了。
具体解决方案
1. 调整Session超时时间
确保 Session 超时时间大于你的请求处理时长,在 web.config 里修改配置:
<system.web> <sessionState mode="InProc" timeout="30" /> <!-- 建议设为30分钟,按需调整 --> </system.web>
2. 避免长时间阻塞请求(推荐方案)
别用 Thread.Sleep 这种同步阻塞操作,实际业务里的耗时任务应该用异步处理或者后台任务框架(比如 Hangfire),让请求快速返回、释放 Session 锁。比如改成异步版本:
[HttpPost] public async Task<ActionResult> Test() { Session["mykey"] = DateTime.Now.ToString("HH:ss"); // 异步等待不会阻塞请求线程,能更快释放资源 await Task.Delay(120000); return View(); }
3. 调整应用程序池设置
在 IIS 里找到你的应用程序池,进入高级设置:
- 把「闲置超时(分钟)」设为更大的值(比如30),避免因长时间无新请求触发回收;
- 调整「回收」相关规则,比如取消「固定时间间隔(分钟)」的自动回收,或设为更大的间隔。
4. 改用非InProc的Session存储模式
如果是多服务器部署或者应用池频繁回收的场景,可以改用 StateServer 或 SQLServer 模式存储 Session,这些模式不会因为应用池回收丢失 Session,锁机制也更灵活。
调试小技巧
在第二次提交请求时,先检查 Request.Cookies["ASP.NET_SessionId"] 的值是否和第一次相同:
- 如果不同,说明浏览器发送了新的 Session ID,问题出在 Cookie 丢失或 Session 过期;
- 如果相同,说明 Session 被清空,大概率是应用池回收导致的。
内容的提问来源于stack exchange,提问作者tuq
相关产品推荐
相关产品推荐

