在普通的.net web服务应用中HTTP会话状态的替代方案

本文关键字:会话状态 HTTP 方案 服务 net web 应用 | 更新日期: 2023-09-27 17:50:00

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

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

应用程序的第一次迭代显示性能提高了一个数量级;然而,随着我们开始构建越来越多的web服务,应用程序的性能现在与ASP的性能不相上下。净豁免。

经过大量的google/灵魂搜索和负载测试,很明显,HTTP会话是罪魁祸首。从本质上讲,每次读取(有时只是将Session包含在web服务方法作用域中)都是一个阻塞调用,它会带来500ms的延迟。一旦你知道去哪里看,这在MSDN文献中有很好的记录。在实现过程中,Session(如果由同一用户的多个web服务使用)将异步请求转换为具有500ms缓冲区的同步请求。目前,我们通过将所有AJAX调用链接为彼此的"成功"事件来缓解这一问题,使它们成为来自客户端的同步请求。这消除了在一个被锁定的Session对象上请求读所导致的500ms的延迟。

使客户端应用程序以"同步"方式运行已经解决了许多性能问题;然而,这只是一个短期的权宜之计。

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

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

这个问题是否有其他的解决方案,可能需要较少的努力来实现?

在普通的.net web服务应用中HTTP会话状态的替代方案

解决你的问题真的很容易。

  1. 关闭web会话。
  2. 在sql server中创建表:

    create table Session(SessionId int(或guid)……)

  3. 创建单独的表,这些表具有回会话表的外键(使用delete cascade)并存储会话特定信息

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

投入更多的硬件!

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

设置好状态服务器后,需要设置web配置以使用新机器。这里有一个很好的过程描述,但简而言之,你设置网页。config的system.web.sessionState元素如下:

<?xml version="1.0"?>
<configuration>
    <system.web>
        <sessionState
            mode="StateServer"
            stateConnectionString="tcpip=your_server_ip:42424"
            cookieless="false"
            timeout="20" />
    </system.web>
</configuration>

现在,如果你想要真正的繁重任务,你可以有许多状态服务器,并编写自己的例程来解析哪个服务器包含会话状态。在这里查看该过程的描述。这个策略可以帮助您在不放弃使用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里?会话中实际存储了多少数据?您是否真的在每次请求时都使用加载到会话中的所有数据?

很难给你真正的答案,如果没有更好地理解你的问题领域:你必须保持状态,你使用的对象有多大,你有多少流量,等等。