2009-06-15 147 views
43

好吧,我已经得到了这个完全罕见的负载均衡PHP网站的独特场景。令人失望的是 - 它以前不是负载平衡的。现在我们开始发现问题了......负载均衡群集中的PHP会话 - 如何?

目前唯一的问题是PHP会话。当然,最初没有人想到这个问题,所以PHP会话配置保持其默认值。因此,两台服务器都拥有自己的小会话文件,而悲伤的是获取下一个请求的用户被抛出到另一台服务器,因为他没有在第一个服务器上创建的会话。

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

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


补充:澄清 - 我希望这是一个标准的解决方案标准的情况。仅供参考 - 我有一个MySQL数据库可用。当然,必须有一些现成的代码可以解决这个问题吗?当然,我可以写我自己的会话保存的东西, Greg指出的 auto_prepend选项似乎很有前途 - 但这会让人觉得重新发明轮子。 :P
添加2:负载平衡DNS基础。我不知道这是如何工作的,但我想这应该是像 this
新增3: OK,我看到一个解决方案是使用 auto_prepend选项在每个脚本插入到 session_set_save_handler()打个电话,写我自己的DB留存,也许在调用 memcached扔有更好的表现。很公平。

是否还有一些方法可以避免自己编码这一切?就像一些着名且经过充分测试的PHP插件一样?

增加了很多,很久以后:这是我到底去的方式:How to properly implement a custom session persister in PHP + MySQL?

而且,我只是手动包括会话处理器中的所有页面。

回答

31

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

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

+5

这不是正确的方法。问题是PHP会话,忘记数据库,我们正在谈论PHP。这个解决方案只是一个解决方法。 – Daniel 2011-12-14 13:37:16

3

要做的最简单的事情就是配置您的负载均衡器始终将同一会话发送到同一台服务器。

如果你仍然想使用session_set_save_handler那么也许看看的auto_prepend。

+0

负载平衡是用DNS条目完成的。主机名解析为两个不同的IP地址,浏览器随机选择一个。或者类似的东西 - 我真的不知道详情。但是AFAIK没有负载均衡器。 “auto_prepend”看起来很有前途。 – 2009-06-15 08:14:14

+0

+1使用auto_prepend在每个脚本之前插入session_set_save_handler函数 – Galen 2009-06-15 08:41:03

+2

听起来就像您在旅途中有一个“Round Robin DNS” - http://en.wikipedia.org/wiki/Round_robin_DNS。我会说,至少说这个“解决方案”负载平衡,更好。 – Ian 2009-06-15 08:54:44

1

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

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

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

6

你没有提到你用于负载平衡的技术(软件,硬件等);但无论如何,解决您的问题的方法是在负载均衡器上使用“粘性会话”。总而言之,这意味着当来自“新”访问者的第一个请求进入时,它们被分配到集群中的特定服务器:所有未来对其会话生命周期的请求将被发送到该服务器。实际上,这意味着在单个服务器上编写的应用程序可以通过零/少量代码更改扩展到平衡的环境。

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

至于软件平衡器,它归结为你正在使用的。对于Apache有上的mod_proxy的stickysession财产 - 的通过谷歌的文章和大量的获得与PHP会话(for example


编辑这个工作: 从原来的问题之后发布的其他意见,这听起来像你“平衡”是通过循环DNS完成的,因此上述可能不适用。我会避免进一步评论,并开始对循环赛DNS的火焰。

+0

我没有选择这个解决方案,我也不能改变它。 – 2009-06-15 09:02:35

1

你也可以尝试使用内存缓存的会话处理程序

1

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

编辑:您也可以使用外部服务,如memcachedb(持久和快速),并将会话信息存储在memcachedb索引中,并使用内容的哈希或甚至会话ID对其进行标识。

17

我们处理这个问题的方式是通过memcached。它所需要的是改变类似于以下php.ini中:

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

我们使用AWS ElastiCache,所以服务器的路径是一个域名,但我敢肯定,这将会是本地的memcached类似的为好。

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

1

如果你有时间,你还是要检查更多的解决方案,看看 http://redis4you.com/articles.php?id=01 ..

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

0

可能为时已晚,但检查了这一点:http://www.pureftpd.org/project/sharedance

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

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

0

当涉及到负载平衡群集中的php会话处理时,最好有粘滞会话。为此要求正在维护负载均衡器的数据中心网络启用粘滞会话。一旦启用,你将不需要担心在php端会话