ASP.NET MVC中应用程序池重新启动会发生什么?

3

我曾经在服务器上使用Session来存储客户端请求的数据。但是在研究过程中,我发现stackoverflow上的各种答案都指出,在ASP.NET MVC中不应该使用Session。主要原因是:生产服务器的应用程序池在其生命周期内经常会被回收,这也会导致Session被回收。

因此,我考虑用可反序列化的字符串“...”来替换Session对象。我的整个关注点是:包含此字符串(可反序列化为对象)的单例对象在应用程序池重新启动时必须不会损坏/回收或重新初始化。

所以我的最终问题是:在应用程序池回收时会发生什么?只有Session会被回收吗?还是整个内存都会被回收和重新初始化?

我的目标Web服务器是Microsoft ASP.NET with MVC。


只是补充一下这个旧答案,你真的不应该使用session。在我看来,这是糟糕的代码味道。过度依赖session可能会创建不符合Web标准的应用程序。比如无法收藏URL,因为新用户无法正确设置会话状态以加载它。这会导致开发中出现很多错误。相反,您应该使用自己的持久性,例如数据库,即Entity Framework 6+或PetaPoco等,并将其与sql server或postgreSql等后端配对。 - Ryan Mann
如果您没有使用 session,你可能会想,如何在请求中获取数据呢?您可以在每个请求中查找它,进行数据库调用来获取它。但是,现在已经是2021年了,我们不需要再担心后端缓存的问题,而可以让 UI 在前端进行缓存。随着 SPA 设计和 URL 状态等,前端将缓存内容,后端无需再担心它。99% 的情况下,不需要进行缓存,但仍有一些情况下需要进行缓存,但缓存不需要涉及会话状态。 - Ryan Mann
3个回答

3
当应用程序进行回收时,运行网站的Windows进程w3wp.exe会结束并创建一个新的进程。一个应用程序池可能有多个工作进程,此时它们全部结束,只保留一个进程,并在需要时创建新的工作进程。
当这种情况发生时,网站代码中存储在内存中的所有内容都会丢失,包括进程内会话信息。
然而,.Net会话状态可以以两种模式工作:进程内或数据库。您可以使用aspnet_regsql工具在SQL Server中创建一个数据库来存储会话信息,然后更改web.config文件以使会话运行在数据库中。您可以使用相同的会话API,在两种模式下都能正常工作。但将其置于数据库模式会使其将所有内容持久化到数据库中,而不是进程内存中。因此,当应用程序池发生回收时,您什么都不会丢失。
RegSql文档:https://msdn.microsoft.com/library/ms229862(v=vs.100).aspx 精心设计的ASP.Net站点(无论是MVC、Web Forms、WebApi(1/2)等)应该被设计成能够从任何回收中完全恢复过来。网站回收不应该破坏您的网站。

值得注意的是,应用程序不应该需要在会话中存储太多东西,实际上什么都不需要。我已经构建了数百个应用程序,从未使用过会话。我使用cookie,但只有在需要数据在JS层中持久化跨页面加载以维护UI状态时才这样做,例如记住您所在的选项卡等。这也考虑到声明身份验证,其中可以包含作为身份验证层一部分所需的状态信息(用户ID、用户名、角色等),并且将持久保存到声明cookie中。 - Ryan Mann

1
重新启动应用程序池将清空您的AppDomain以及其中的所有内容,包括所有静态值。这就是为什么它会首先丢失会话状态的原因。
您可能需要一个数据库。

例如,我有一个单例用户定义的集合。它也会消失和崩溃吗?这个用户定义的集合将包含可反序列化的字符串到对象。我想保留那个可反序列化的字符串。所以,这个单例集合也会消失吗? - Usman
1
单例将在新的应用程序域中重新初始化 - 当应用程序池回收时,应用程序域内的所有内存状态都会丢失。 - Preston Guillot

1

SLaks已经回答了你的问题。这是解决方案 -

在ASP.Net MVC中,我们不像Web Form一样使用Session State。

然而,你仍然可以使用Session State,但你需要使用外部Session State提供程序,而不是默认的InProc 模式 - 值和变量存储在本地Web服务器上的内存中。

你有几个选择 -


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接