负载平衡群集中的PHP会话 - 如何?

时间:2009-06-15 07:52:37

标签: php session load-balancing cluster-computing

好的,所以我有一个非常罕见的负载平衡PHP网站的独特场景。无赖是 - 它不习惯负载平衡。现在我们开始遇到问题......

目前唯一的问题是PHP会话。当然没有人首先想到这个问题所以PHP会话配置保持默认值。因此,两个服务器都有自己的一小部分会话文件,并且有一个用户将下一个请求抛给另一个服务器,因为它没有在第一个服务器上创建的会话。

现在,我一直在阅读PHP手册,了解如何解决这种情况。在那里我找到了session_set_save_handler()的好功能。 (巧合的是,this topic在SO上)整洁。除了我必须在网站的所有页面中调用此功能。未来页面的开发人员也必须记住一直调用它。感觉有点笨拙,更不用说可能违反了十几种最佳编码习惯。如果我可以翻转一些全局配置选项和Voilà,会更好一些 - 会话都可以神奇地存储在数据库或内存缓存中。

关于如何做到这一点的任何想法?

<小时/> 已添加:澄清 - 我希望这是标准解决方案的标准情况。仅供参考 - 我有MySQL数据库可用。当然必须有一些现成的代码可以解决这个问题吗?当然,我可以编写自己的会话保存内容,而Greg指出的auto_prepend选项看起来很有希望 - 但这会让人觉得重新发明轮子。 :P
已添加2:负载均衡基于DNS。我不确定这是如何工作的,但我想它应该像this
添加3:好的,我看到一个解决方案是使用auto_prepend选项在每个脚本中插入对session_set_save_handler()的调用并编写我自己的数据库容器,可能会抛出调用到memcached以获得更好的表现。很公平。

还有一些方法可以避免自己编码吗?就像一些着名且经过良好测试的PHP插件一样?

添加了很多,很久以后:这就是我最终的方式:How to properly implement a custom session persister in PHP + MySQL?

此外,我只是在所有页面中手动包含会话处理程序。

10 个答案:

答案 0 :(得分:32)

您可以将PHP设置为处理数据库中的会话,因此所有服务器共享相同的会话信息,因为所有服务器都使用相同的数据库。

一个很好的教程可以是found here

答案 1 :(得分:20)

我们处理这个的方式是通过memcached。所需要的只是更改php.ini,类似于以下内容:

session.save_handler = memcache
session.save_path = "tcp://path.to.memcached.server:11211"

我们使用AWS ElastiCache,因此服务器路径是一个域,但我确信它对于本地memcached也是类似的。

此方法不需要更改任何应用程序代码。

答案 2 :(得分:7)

您没有提到您用于负载平衡的技术(软件,硬件等);但无论如何,您的问题的解决方案是在负载均衡器上使用“粘性会话”。

总之,这意味着当来自“新”访问者的第一个请求进入时,会从群集中为他们分配一个特定服务器:所有将来对其会话生命周期的请求都将定向到该服务器。实际上,这意味着在单个服务器上编写的应用程序可以扩展到平衡环境,代码更改为零/很少。

如果您使用的是硬件平衡器,例如Radware设备,则粘性会话将配置为群集设置的一部分。硬件设备通常会为您提供更细粒度的控制:例如,为新用户分配哪个服务器(他们可以检查健康状况等,并选择最健康/最少使用的服务器),以及更多控制服务器时发生的情况失败并退出群集。硬件平衡器的缺点是成本 - 但它们是值得的。

至于软件平衡器,它取决于您使用的是什么。对于Apache,mod_proxy上有一个stickysession属性 - 并且很多文章通过谷歌来使用php会话(for example


编辑: 从原始问题之后发布的其他评论中,听起来您的“平衡”是通过循环DNS完成的,因此上述内容可能不适用。我将避免进一步发表评论并开始对抗循环dns。

答案 3 :(得分:4)

如果您有时间并且仍想查看更多解决方案,请查看 http://redis4you.com/articles.php?id=01 ..

使用redis你是容错的。从我的观点来看,由于这种稳健性,它可能比memcache解决方案更好。

答案 4 :(得分:3)

最简单的方法是将负载均衡器配置为始终将同一会话发送到同一服务器。

如果您仍想使用session_set_save_handler,那么可以查看auto_prepend。

答案 5 :(得分:2)

当我们遇到这种情况时,我们实现了一些存在于公共标题中的代码。

基本上对于每个页面,我们检查是否知道会话ID。如果我们不检查我们是否处于您描述的情况,通过检查我们是否已在数据库中存储了sesion数据。否则我们只是开始一个新的会话。

显然,这需要将所有相关数据复制到数据库中,但如果将会话数据封装在单独的类中,则可以正常工作。

答案 6 :(得分:2)

你也可以尝试使用memcache作为会话处理程序

答案 7 :(得分:2)

如果您正在使用php会话,您可以与NFS共享/ tmp目录,我认为会话存储在群集中的所有服务器之间。这样你就不需要数据库了。

编辑:您还可以使用像memcachedb这样的外部服务(持久和快速),并将会话信息存储在memcachedb索引中,并使用内容的哈希值甚至会话ID来识别它。

答案 8 :(得分:1)

可能为时已晚,但请查看:http://www.pureftpd.org/project/sharedance

  

Sharedance是一种集中临时密钥/数据的高性能服务器   远程主机上的对,没有SQL的开销和复杂性   数据库中。

     

它主要用于在Web池之间共享缓存和会话   服务器。通过简单的PHP API和访问共享服务器是微不足道的   它符合PHP 4和PHP 5会话处理程序的期望。

答案 9 :(得分:0)

在负载平衡群集中进行php会话处理时,最好使用Sticky Sessions。为此请询问维护负载均衡器的数据中心网络以启用粘性会话。一旦启用,您就不必担心在php结束时的会话