【发布时间】:2011-10-26 21:54:50
【问题描述】:
我从一个非常喜欢会话变量的开发人员那里继承了一个项目。他用它们来存储各种全球性的东西——数据表、数据集、文件位置、连接字符串等。我有点担心这可能不是很有可扩展性,而且我们确实有可能立即拥有更多用户未来。
我的担心是否正确,如果是,为什么? 有没有一种简单的方法可以查看目前在实时服务器上使用了多少内存? 重构这个以使用更好的解决方案的最佳方法是什么?
【问题讨论】:
我从一个非常喜欢会话变量的开发人员那里继承了一个项目。他用它们来存储各种全球性的东西——数据表、数据集、文件位置、连接字符串等。我有点担心这可能不是很有可扩展性,而且我们确实有可能立即拥有更多用户未来。
我的担心是否正确,如果是,为什么? 有没有一种简单的方法可以查看目前在实时服务器上使用了多少内存? 重构这个以使用更好的解决方案的最佳方法是什么?
【问题讨论】:
是的,我会说你确实有一些担心的理由。过度使用会话会导致很多性能问题。理想情况下,会话应该只用于特定于用户的信息。显然这条规则有例外,但在重构时请记住这一点。
至于重构本身,我会考虑缓存任何非用户特定的大型对象,并删除不需要在会话中的任何内容。不要害怕在需要时访问数据库以检索信息。选择对服务器造成最小整体压力的选项。诀窍是保持平衡并在应用程序的各个层上尽可能均匀地分配权重。
【讨论】:
这可能是由于设计不佳,是的,如果您打算增加流量或扩大网站规模,您应该担心。
连接字符串应存储在web.config 中。似乎您必须重新设计数据层以及页面如何相互传递数据以避免在 Session 中存储数据表和数据集。例如,不是将整个数据集存储在 Session 中,而是通过 url 存储或传递,而是可以使用一些小东西(如 ID)来重新查询数据库。
【讨论】:
会话总是会损害可伸缩性。但是,一旦使用了会话,在会话中增加一点数据的影响并没有那么糟糕。
不过,它必须存储在某个地方,必须从某个地方检索,所以它会产生影响。如果你不得不搬到一个网络农场来处理非常成功的事情,那真的会很痛苦,因为这很难以可扩展的方式做好。我会从真正意义上的全球性(在所有会话之间共享)开始,并将其移动到一个真正全球可访问的位置。
那么任何依赖于前一个请求的东西,我都会被那个请求发送。
同时执行这两项操作将大大减少它们的使用量(也许足以关闭会话并获得巨大的可扩展性提升)。
【讨论】:
根据 IIS 版本,使用 Session 存储状态可能会对缩放产生影响。 IIS 的更高版本更好。 但是,我遇到的主要问题是会话过期,然后您的数据丢失;您可以提供自己的 Session_OnEnd 处理程序,以便重新生成会话。
【讨论】:
总的来说是的,你应该关心这个。
会话是内存中的“每个用户”类型的存储。查看 ASP.NET 工作进程的内存使用情况可以让您了解内存使用情况,但如果您想深入了解其中的内容,您可能需要使用第三方工具。此外,会话变得非常“有趣” " 当您开始负载平衡等时。
ConnectionStrings 和其他不是“每个用户”的信息实际上不应该在“每个用户”存储位置处理。
至于为此创建解决方案,很大程度上取决于数据本身,因为您可能需要找到多个其他机会/位置来获取/存储信息。
【讨论】:
您对此感到担忧是对的。
连接字符串应存储在 Web.config 中并始终从那里读取。 Web.config 文件被缓存,因此将内容存储在其中然后在 Session 上是多余且不必要的。对于文件的位置也可以这样说:您可能可以在 web.config 的 appSettings 部分中创建键值对来存储此信息。
就存储数据集、数据表等而言;如果从数据库中获取这些信息非常昂贵并且数据不是太大,我只会将这些信息存储在Session 上。很多人倾向于做这种事情而没有意识到他们的查询非常快并且数据库连接是池化的。
如果从数据库中获取数据确实需要很长时间,我首先要尝试解决的问题是查询速度。我缺少索引吗?我的查询的执行计划显示了什么?我是在做表扫描等等吗?
我目前在Session(或Cache)上存储信息的一种情况是,当我确实必须调用一个平均需要超过 2 秒才能检索我需要的内容的外部 Web 服务时。一旦我获得了这些数据,我就不需要在每次点击页面时都再次获得,所以我缓存了它。
显然,一个在Session 上存储几乎所有内容的应用程序将存在可伸缩性问题,因为内存是有限的资源。
【讨论】:
如果内存是问题,为什么不将会话模式更改为 sql server,以便您可以将会话数据存储在 sql server 中,这需要很少的代码更改。
如何在sql server中存储session数据: http://msdn.microsoft.com/en-us/library/ms178586.aspx
问题是存储在 sql server 中的类必须是可序列化的,您可以使用 json.net 来做到这一点。
【讨论】: