负载平衡集群中的 PHP 会话 - 如何?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/994935/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PHP sessions in a load balancing cluster - how?
提问by Vilx-
OK, so I've got this totally rare an unique scenario of a load balanced PHP website. The bummer is - it didn't used to be load balanced. Now we're starting to get issues...
好的,所以我有一个完全罕见的负载平衡 PHP 网站的独特场景。令人失望的是 - 它过去没有进行负载平衡。现在我们开始遇到问题......
Currently the only issue is with PHP sessions. Naturally nobody thought of this issue at first so the PHP session configuration was left at its defaults. Thus both servers have their own little stash of session files, and woe is the user who gets the next request thrown to the other server, because that doesn't have the session he created on the first one.
目前唯一的问题是 PHP 会话。一开始自然没有人想到这个问题,所以 PHP 会话配置保留为默认值。因此,两台服务器都有自己的一小部分会话文件,而将下一个请求抛出到另一台服务器的用户是不幸的,因为那没有他在第一个服务器上创建的会话。
Now, I've been reading PHP manual on how to solve this situation. There I found the nice function of session_set_save_handler(). (And, coincidentally, this topicon SO) Neat. Except I'll have to call this function in all the pages of the website. And developers of future pages would have to remember to call it all the time as well. Feels kinda clumsy, not to mention probably violating a dozen best coding practices. It would be much nicer if I could just flip some global configuration option and Voilà- the sessions all get magically stored in a DB or a memory cache or something.
现在,我一直在阅读有关如何解决这种情况的 PHP 手册。在那里我发现了session_set_save_handler(). (而且,巧合的是,这个话题关于 SO)整洁。除了我必须在网站的所有页面中调用这个函数。未来页面的开发人员也必须记住一直调用它。感觉有点笨拙,更不用说可能违反了十几种最佳编码实践。如果我可以只翻转一些全局配置选项和Voilà会更好- 会话都神奇地存储在数据库或内存缓存或其他东西中。
Any ideas on how to do this?
关于如何做到这一点的任何想法?
Added:补充:澄清 - 我希望这是标准解决方案的标准情况。仅供参考 - 我有一个可用的 MySQL 数据库。肯定有一些现成的代码可以解决这个问题吗?当然,我可以编写自己的会话保存内容和
auto_prependauto_prepend选项GregGreg看起来很有前途——但这感觉就像是在重新发明轮子。:P
Added 2:补充 2:负载均衡是基于 DNS 的。我不确定这是如何工作的,但我想它应该是这样的this这个。
Added 3:添加 3:好的,我看到一个解决方案是使用
auto_prependauto_prepend选项session_set_save_handler()session_set_save_handler()在每个脚本中插入一个调用并编写我自己的数据库持久化程序,也许会调用 to 以memcachedmemcached获得更好的性能。很公平。Is there also some way that I could avoid coding all this myself? Like some famous and well-tested PHP plugin?
还有什么方法可以避免我自己编写所有这些代码吗?喜欢一些著名且经过良好测试的 PHP 插件?
Added much, much later:This is the way I went in the end: How to properly implement a custom session persister in PHP + MySQL?
很久以后添加:这就是我最后的方式:如何在 PHP + MySQL 中正确实现自定义会话持久器?
Also, I simply included the session handler manually in all pages.
此外,我只是在所有页面中手动包含会话处理程序。
采纳答案by Oliver Friedrich
You could set PHP to handle the sessions in the database, so all your servers share same session information as all servers use the same database for that.
您可以设置 PHP 来处理数据库中的会话,因此您的所有服务器都共享相同的会话信息,因为所有服务器都为此使用相同的数据库。
A good tutorial for that can be found here.
一个很好的教程可以在这里找到。
回答by Doug Johnson
The way we handle this is through memcached. All it takes is changing the php.ini similar to the following:
我们处理这种情况的方式是通过 memcached。所需要的只是更改类似于以下内容的 php.ini:
session.save_handler = memcache
session.save_path = "tcp://path.to.memcached.server:11211"
We use AWS ElastiCache, so the server path is a domain, but I'm sure it'd be similar for local memcached as well.
我们使用 AWS ElastiCache,所以服务器路径是一个域,但我相信本地 memcached 也是类似的。
This method doesn't require any application code changes.
此方法不需要任何应用程序代码更改。
回答by Ian
You don't mentioned what technology you are using for load balancing (software, hardware etc.); but in any case, the solution to your problem is to employ "sticky sessions" on the load balancer.
您没有提到您用于负载平衡的技术(软件、硬件等);但无论如何,解决您的问题的方法是在负载平衡器上使用“粘性会话”。
In summary, this means that when the first request from a "new" visitor comes in, they are assigned a specific server from the cluster: all future requests for the lifetime of their session are then directed to that server. In practice this means that applications written to work on a single server can be up-scaled to a balanced environment with zero/few code changes.
总而言之,这意味着当来自“新”访问者的第一个请求进来时,他们会从集群中分配一个特定的服务器:他们会话生命周期内的所有未来请求都将被定向到该服务器。在实践中,这意味着编写在单个服务器上工作的应用程序可以扩展到一个平衡的环境,而代码更改为零/很少。
If you are using a hardware balancer, such as a Radware device, then the sticky sessions is configured as part of the cluster setup. Hardware devices usually give you more fine-grained control: such as which server a new user is assigned to (they can check for health status etc. and pick the most healthy / least utilised server), and more control of what happens when a server fails and drops out of the cluster. The drawback of hardware balancers is the cost - but they are worth it imho.
如果您使用的是硬件平衡器,例如 Radware 设备,则粘性会话将配置为集群设置的一部分。硬件设备通常为您提供更细粒度的控制:例如将新用户分配到哪个服务器(他们可以检查健康状况等并选择最健康/最少使用的服务器),以及对服务器发生的情况的更多控制失败并退出集群。硬件平衡器的缺点是成本 - 但恕我直言,它们是值得的。
As for software balancers, it comes down to what you are using. For Apache there is the stickysession property on mod_proxy - and plenty of articles via google to get this working with the php session ( for example)
至于软件平衡器,这取决于您使用的是什么。对于 Apache,mod_proxy 上有 stickysession 属性 - 以及通过 google 获得的大量文章以使其与 php 会话一起工作(例如)
Edit: From other comments posted after the original question, it sounds like your "balancing" is done via Round Robin DNS, so the above probably won't apply. I'll refrain from commenting further and starting a flame against round robin dns.
编辑:从原始问题之后发布的其他评论来看,听起来您的“平衡”是通过循环 DNS 完成的,因此上述内容可能不适用。我将避免进一步评论并开始反对循环 dns。
回答by Greg
The easiest thing to do is configure your load balancer to always send the same session to the same server.
最简单的做法是将负载均衡器配置为始终将相同的会话发送到相同的服务器。
If you still want to use session_set_save_handlerthen maybe take a look at auto_prepend.
如果你仍然想使用session_set_save_handler那么也许看看 auto_prepend。
回答by Alex Moleiro
If you have time and you still want to check more solutions, take a look at http://redis4you.com/articles.php?id=01..
如果您有时间,但仍想查看更多解决方案,请查看 http://redis4you.com/articles.php?id=01..
Using redis you are fault tolerant. From my point of view, it could be better than memcache solutions because of this robustness.
使用 redis 你是容错的。在我看来,由于这种健壮性,它可能比内存缓存解决方案更好。
回答by Khriz
If you are using php sessions you could share with NFS the /tmp directory, where I think the sessions are stored, between all the servers in the cluster. That way you don't need database.
如果您使用的是 php 会话,您可以与 NFS 共享 /tmp 目录,我认为会话存储在集群中的所有服务器之间。这样你就不需要数据库了。
Edited: You can also use an external service like memcachedb (persistent and fast) and store the session info in the memcachedb index and indentify it with a hash of the content or even the session ID.
编辑:您还可以使用像 memcachedb(持久且快速)这样的外部服务,并将会话信息存储在 memcachedb 索引中,并使用内容的哈希值甚至会话 ID 来标识它。
回答by Claudio Bredfeldt
Might be too late, but check this out: http://www.pureftpd.org/project/sharedance
可能为时已晚,但请查看:http: //www.pureftpd.org/project/sharedance
Sharedance is a high-performance server to centralize ephemeral key/data pairs on remote hosts, without the overhead and the complexity of an SQL database.
It was mainly designed to share caches and sessions between a pool of web servers. Access to a sharedance server is trivial through a simple PHP API and it is compatible with the expectations of PHP 4 and PHP 5 session handlers.
Sharedance 是一种高性能服务器,用于在远程主机上集中临时密钥/数据对,没有 SQL 数据库的开销和复杂性。
它主要设计用于在 Web 服务器池之间共享缓存和会话。通过一个简单的 PHP API 访问共享服务器是微不足道的,它与 PHP 4 和 PHP 5 会话处理程序的期望兼容。
回答by PaulJWilliams
When we had this situation we implemented some code that lives in a common header.
当我们遇到这种情况时,我们实现了一些位于公共标头中的代码。
Essentially for each page we check if we know the session Id. If we dont we check if we're in the situation whehich you describe, by checking if we have stored sesion data in the DB.Otherwise we just start a new session.
基本上对于每个页面,我们检查我们是否知道会话 ID。如果我们不检查我们是否处于您描述的情况,通过检查我们是否在 DB 中存储了会话数据。否则我们只是开始一个新会话。
Obviously this requires all relevant data to be copied to the DB, but if you encapsulate your session data in a seperate class then it works OK.
显然,这需要将所有相关数据复制到数据库中,但是如果您将会话数据封装在单独的类中,则它可以正常工作。
回答by PaulJWilliams
you could also try using memcache as session handler
您也可以尝试使用 memcache 作为会话处理程序
回答by harigorana
When it comes to php session handling in the Load Balancing Cluster, it's best to have Sticky Sessions. For that ask the network of datacenter who is maintaining the load balancer to enable the sticky session. Once that is enabled you'll don't need worry about sessions at php end
在负载平衡集群中处理 php 会话时,最好使用粘性会话。为此,请询问维护负载平衡器的数据中心网络以启用粘性会话。启用后,您将无需担心 php 端的会话

