我最近有机会将一个 Web 应用程序从使用 Nginx 代理“负载均衡器”迁移到使用 F5 负载均衡器。不幸的是,在迁移过程中,很明显memcached
需要将会话存储从 Nginx 代理服务器移动到“某个地方”。我的想法是,我应该memcached
在所有 3 个 Web 服务器(位于池中 F5 后面的服务器)上安装并使用php-memcache
或php-memcached
保存会话。问题如下:
我尝试过这两种方式php-memcache
,但当php-memcached
其中一台服务器宕机时,它们都无法正常工作。我最近尝试的是这种配置:
memcached
版本 2.2.0 的配置设置如下:
session.save_handler = memcached session.save_path = "172.29.104.13:11211,172.29.104.14:11211"
memcached.ini
除此以外我没有什么特别的extension=memcached.so
。
在服务器 1 和 2 上都使用此配置(我暂时移除了 3 进行测试),我将 JMeter 指向 F5 VIP 并开始流量。我可以memcached.log
在两个系统上看到(守护进程),虽然没有花时间去解密,但它开始运行。
然后,如果我停止其中一个memcached
守护进程,流量就会开始失败,我的回报是
session_start(): Write of lock failed
memcached
剩下的就是。
归根结底,我的目标很简单 - 我需要能够 a) 不在memcached
单个服务器上运行(单点故障),并且集群需要能够抵御池成员的故障。
我也试过了,php-memcache
但是也失败了。php-memcache
配置如下:
memcache
版本 3.0.8(测试版)的配置设置:
session.save_handler = memcache session.save_path = "tcp://172.29.104.13:11211, tcp://172.29.104.14:11211"
以及memcache.ini
:
扩展=memcache.so [内存缓存] memcache.dbpath="/var/lib/memcache" memcache.maxreclevel=0 memcache.maxfiles=0 memcache.archivememlim=0 memcache.maxfilesize=0 memcache.maxratio=0 memcache.hash_strategy=一致 memcache.allow_failover=1 memcache.session_redundancy=2
这里的错误只是无效的会话令牌(对我而言这意味着剩下的服务器实际上没有存储会话令牌,这意味着保存会话的复制没有激活)。
我还没有考虑将会话持久性重新放到 F5 上,尽管作为最后的手段我可以这样做,并且尝试连接到丢失成员的客户端必须重新进行身份验证。
答案1
让客户端在 cookie 中为您存储会话状态要简单得多。这意味着服务器端根本不需要会话存储,只需几微秒的 CPU 使用率来解密和验证 cookie。由于 CPU 是数据中心中最丰富的资源,因此这种方案的性能将比从 memcached 或任何其他服务器会话存储中查找要好得多。
看https://github.com/ascorbic/php-stateless-cookies对于一个实现,还有许多其他的实现。注意会话数据应该加密,但是必须通过 HMAC 或 AEAD 密码进行身份验证。除非您是密码学家,否则不要自己编写此代码;请使用经过严格审查的 cryoto 库。
Facebook 使用这种技术,因此任何服务器都可以回答任何用户请求,即使用户会话在另一个数据中心启动。