普通的.NET Web服务应用程序中HTTP会话状态的替代方案

经过与ASP.NET页面生命周期及其性能的长期斗争,我们已经开始重构我们的Web应用程序,以在客户端实现Web服务(普通的.asmx .NET Web服务)和jQuery。 注意:这不以任何方式实现MVC或ASP.NET,这些只是Web服务。

在应用程序的两个分配中,我们在单个页面中动态生成所有内容。 在ASP.NET分配中,这意味着(由于页面生命周期)整个页面需要被拆除并重建(几乎)每个AJAX调用或更改为Web表单。 这为旨在为许多并发用户提供服务的应用程序带来了巨大的可扩展性问题。 在Web服务/ jQuery分配中,我们可以有选择地只关注需要向服务器发送或接收数据的DOM元素,这意味着更少的请求和更快的用户体验。

该应用程序的第一次迭代显示性能提升了一个数量级; 但是,随着我们开始构建越来越多的Web服务,应用程序的性能现在与ASP.NET分配的性能相当。

经过大量谷歌搜索/灵魂搜索和负载测试后,很明显HTTP Session是罪魁祸首。 本质上,每次读取(有时通过简单地在Web服务方法范围中包括Session)都是阻塞调用,它引入了500ms的延迟。 一旦你知道在哪里看,这在MSDN文献中有详细记载。 实现时,Session(如果由同一用户的多个Web服务使用)将异步请求转换为具有500ms缓冲区的同步请求。 我们通过将所有AJAX调用链接为彼此的“成功”事件来缓解这种情况,从而使它们成为来自客户端的同步请求。 这消除了请求对锁定的Session对象进行读取所导致的500ms延迟。

使客户端应用程序以“同步”方式运行已解决了许多性能问题; 然而,这只是短期内的一个临时解决方案。

什么可行的(可扩展的!)替代Session存在,再次记住,我们不是在ASP.NET或MVC或WCF等? 我们最大的障碍是我们的元数据集合的持久性,该集合在登录时为每个用户初始化。 这是app中最昂贵的操作(10倍或更多),而且我们只想执行一次。 会话提供了一种简单的方式,让老一辈流汗,永不回头; 但这种方法看起来不太可行。

一种方法可能是消除这个单一的元数据集合神类,并将这个一神论类演变为半神论的多神论集合。 可以以更低的成本更频繁地完成半神人的实例化。 可行,但需要大量的重构,广泛的开发和QA时间。 另一个候选者只是将所有状态信息存储在数据库中,但这有其自身的成本 – 延迟并非最不重要。

是否有任何其他解决方案可能涉及较低的实施工作量?

解决问题真的很容易。

  1. 关闭整个网站的web.config中的会话
  2. 在sql server中创建一个表:

    创建表Session(SessionId int(或guid)……)

  3. 创建单独的表,将外键返回到会话表(使用删除级联)并存储会话特定信息

  4. 在应用程序端,将SessionId存储在cookie或查询字符串中。 然后,您可以按需查找所需的所有会话信息。 这将比默认会话状态提供程序快得多,因为您只需在获取信息时获取信息! 此外,您不必再在背后携带默认会话对象。

扔更多的硬件!

不,认真。 对于像您这样的站点,您可以将单独的计算机配置为会话状态服务器(请参阅MSDN文档 ),您可以从IIS GUI或命令行执行此操作。

设置状态服务器后,需要设置Web配置以使用新计算机。 这里提供了一个很好的过程描述,但简而言之,您可以设置web.config的system.web.sessionState元素,如下所示:

      

现在,如果你想要真正的重任,你可以拥有许多状态服务器并编写自己的例程来解决哪个服务器包含你的会话状态。 请在此处查看流程说明。 这种策略应该可以帮助您无限制地扩展,而不必放弃使用HttpSession。

如果您的大多数请求只需要对会话的读访问权限,那么您有一个简单的解决方案。 将EnableSessionState属性设置为ReadOnly,它们仅在会话上获取只读锁。 我不确定如何将此应用于Web服务,但我确信有一个等效的设置。

http://msdn.microsoft.com/en-us/library/aa479041.aspx#aspnetsessionstate_topic3

除此之外,ASP.NET会在每个请求的整个持续时间内锁定会话对象,并有效地序列化请求。 允许请求并行运行的一种解决方案是不使用内置会话并推出自己的解决方案。 这里的优点是您可以使用更精细的粒度锁定,因此请求的某些方面必须通过同步并且将以串行方式运行,但每个请求的大部分可以并行运行。

另一种解决方案是简单地减少每个请求的并行调用数。 不要试图并行运行它们。 在客户端批量处理它们并将它们作为单个请求发送。 您最终会减少请求数量的开销,减少单个客户端占用大量资源的可能性,并且很可能在整体和每个聚合请求中获得更好的性能。

如果没有看到您的代码,或者您在会话中加载和存储的内容,实际上很难帮助您。 但是,根据我的经验,会话延迟0.5秒肯定不正常。 我非常希望看到您所指的文档说明是这样的。

写得好的asp.net(无论是webforms,asmx,mvc还是其他选项)肯定是非常可扩展的。

话虽如此,你的会话存储在哪里? 在进程中? IIS状态服务器? 在DB中? 你在会话中真正存储了多少数据? 您是否真的使用几乎每个请求加载到会话中的所有数据?

很难给出真正的答案,而不是更好地理解您的问题领域:您必须保持状态,您用于保持状态的对象有多大,您拥有多少流量等等。