【问题标题】:How to manage session variables in a web cluster?如何管理 Web 集群中的会话变量?
【发布时间】:2010-09-18 10:47:34
【问题描述】:

会话变量通常保存在 Web 服务器 RAM 内存中。

在集群中,客户端发出的每个请求都可以由不同的集群节点处理。对吧?!

所以,在这种情况下……

  • 会话变量会发生什么?它们不是存储在节点 RAM 内存中吗?
  • 如果它没有我的会话变量,或者至少没有我的会话变量,其他节点将如何正确处理我的请求?
  • 此问题由 Web 服务器(Apache、IIS)或语言运行时(PHP、ASP.NET、Ruby、JSP)处理?

编辑:经典 ASP 有一些解决方案吗?

【问题讨论】:

    标签: session cluster-analysis


    【解决方案1】:

    在 ASP.NET 中,您可以将会话数据持久保存到 SQL Server 数据库中,该数据库对集群中的所有 Web 服务器都是通用的。

    配置后(在您网站的 web.config 中),框架会为您处理所有持久性,您可以正常访问会话数据。

    【讨论】:

    • 如何存储在会话变量中的复杂数据,比如对象引用?
    • 任何可以序列化的东西(包括复杂对象)都可以存储,我相信。
    【解决方案2】:

    在 ASP.NET 中有 3 种方法可以存储会话状态。第一个是在进程中,变量存储在内存中。第二种是通过将以下内容放入您的 web.config 文件中来使用会话状态服务:

    <sessionState
        mode="StateServer"
        stateConnectionString="tcpip=127.0.0.1:42424"
        sqlConnectionString="data source=127.0.0.1;user id=sa;password="
        cookieless="false"
        timeout="20" />
    

    您可以在 stateConnectionString 属性中看到,会话状态服务可以位于不同的计算机上。

    第三种选择是使用集中式 SQL 数据库。为此,您在 web.config 中添加以下内容:

    <sessionState
        mode="SQLServer"
        stateConnectionString="tcpip=127.0.0.1:42424"
        sqlConnectionString=
         "data source=SERVERHAME;user id=sa;password="
        cookieless="false"
        timeout="20"
    />
    

    所有这些选项的更多详细信息都写在这里:http://www.ondotnet.com/pub/a/dotnet/2003/03/24/sessionstate.html

    【讨论】:

    【解决方案3】:

    获取一台 Linux 机器并设置 http://www.danga.com/memcached 。与其他方法相比,它的速度是无与伦比的。 (例如cookies、表单隐藏变量、数据库)

    【讨论】:

    • 这是什么?你能解释清楚一点吗?
    • memcached 允许您缓存(注意,不是存储——它不能保证是持久的)给定键的数据。因此,您将从客户端请求中获取会话密钥并从 memcached 中查找会话数据。它速度很快,因此集群的所有成员都可以共享一个实例。
    • 更好的是,在所有网络服务器上设置 memcached。客户端将使用密钥的散列来分配负载并使用更多可用内存。
    【解决方案4】:

    与各种事情一样,“这取决于”。

    有不同的解决方案和方法。

    如前所述,存在会话状态(数据库、memcached、共享文件系统等)集中存储的概念。

    还有集群范围的缓存系统可用,使集群中的所有机器都可以使用本地数据。从概念上讲,它类似于集中式会话状态存储,但此数据不是持久的。相反,它存在于各个节点中,并使用您的提供者提供的某种机制进行复制。

    另一种方法是服务器固定。当客户端第一次访问集群时,某种机制(通常是集群前面的负载均衡器)将客户端固定到特定服务器。在典型的客户端生命周期中,该客户端将整个时间都花在一台机器上。

    对于故障转移机制,集群的每台机器都与另一台机器配对,因此任何会话更改都会与配对机器共享。如果客户端固定的机器遇到问题,客户端将撞到另一台机器。此时,可能由于 cookie 的原因,新机器发现它不是客户端的原始机器,因此它会 ping 原始机器和配对机器以获取客户端会话数据。

    此时客户端很可能被固定到新机器上。

    不同的平台以不同的方式执行此操作,包括根本没有会话状态。

    【讨论】:

      【解决方案5】:

      扩展@yogman 的答案。

      Memcached 真是太棒了!这是一个高性能的分布式对象缓存。

      尽管我提到了分布式,但它基本上就像在您的一个备用/空闲服务器上启动一个实例一样简单,您将其配置为 ip、端口和要使用多少内存,然后就完成了。

      memcached -d -u www -m 2048 -l 10.0.0.8 -p 11211
      

      (以守护程序模式运行 memcached,作为用户 www,IP 10.0.0.8 上的 2048 MB (2 GB) RAM,端口为 11211。)

      从那时起,您向 memcached 请求数据,如果数据尚未缓存,则从原始源中提取数据并将其存储在 memcached 中。我确定您熟悉缓存基础知识。

      在集群环境中,您可以将您的 memcached 链接到集群中,并在您的节点之间复制缓存。 Memcached 在 Linux、Unix 和 Windows 上运行,在您有空闲 RAM 的任何地方启动它并开始使用您的资源。

      memcached 的 API 应该是 generally available。我说 应该 因为我只知道 Perl、Java 和 PHP。但我确信,例如在 Python 中,人们也有办法利用它。有一个memcached wiki,以防您需要指点,或者如果我说得太多,请在 cmets 中告诉我。 ;)

      【讨论】:

        【解决方案6】:

        使用Hazelcast,您可以使用 Hazelcast 分布式地图在集群中存储和共享会话,或者让 Hazelcast Webapp Manager 为您完成所有工作。请查看文档以获取详细信息。 Hazelcast 是一个分布式/分区、超级精简、简单、免费的 Java 数据分发解决方案。

        问候,

        -塔利普

        http://www.hazelcast.com

        【讨论】:

          【解决方案7】:

          正如 Will 所说,大多数负载平衡方法将在分发来自同一客户端的即将到来的请求的方式中使用某种粘性,这意味着一个唯一的客户端将访问同一台服务器,除非该实际服务器出现故障。

          这最大限度地减少了会话数据分发的需要,这意味着只有在服务器最终出现故障时,客户端才会失去他的会话。根据您的应用程序,这或多或少至关重要。在大多数情况下,这不是什么大问题。

          即使是最简单的负载平衡方式(轮询 DNS 查找)也会产生某种粘性,因为大多数浏览器都会缓存实际查找,因此会继续访问它收到的第一条记录,AFAIK。

          通常是运行时负责会话数据,例如在 PHP 中,可以定义自己的会话处理程序,它可以将数据保存到数据库中。默认情况下,PHP 将会话数据存储在文件中,并且可以在 SAN 或同等设备上共享这些文件以共享会话数据。这只是我的一个理论,但从未测试过,因为我们认为丢失会话并不重要并且不希望出现单点故障。

          【讨论】:

            【解决方案8】:

            要实现经典 ASP 的负载平衡,您可以将用户特定值存储在数据库中并在 URL 中传递一个引用唯一 ID 如下。

            在数据库中维护一个会话表,为每条记录生成一个唯一ID。第一次要存储会话特定数据时,在会话表中生成一条记录并将会话值存储在其中。获取新会话记录的唯一 ID,并在您的 Web 应用程序中重写所有链接,以将唯一 ID 作为查询字符串的一部分发送。

            在您需要会话数据的每个后续页面中,使用在查询字符串中传递的唯一 id 查询会话表。

            示例:

            假设您的网站有 4 个页面:Login.asp、welcome.asp、taskList.asp、newtask.asp

            当用户使用 login.asp 页面登录时,验证用户后,在 会话表 中创建一条记录并存储所需的会话特定值(假设用户的 登录本示例的日期/时间)。获取新会话记录的唯一 ID(假设唯一 ID 为 abcd)。

            将您网站中的所有链接附加到下面的唯一ID:

            • welcome.asp?sessionId=abcd
            • tasklist.asp?sessionId=abcd
            • newtask.asp?sessionId=abcd

            现在,如果您想在上述任何网页中显示用户的登录日期/时间,您只需使用 sessionID 参数查询您的会话表 (abcd 在这种情况下)并显示给用户。

            由于标识会话的唯一值是 URL 的一部分,因此为用户提供服务的任何网络服务器都将能够显示正确的登录日期/时间值。

            希望这会有所帮助。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2015-01-08
              • 2012-04-09
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多