容错 Memcached 池中的 PHP 会话存储

容错 Memcached 池中的 PHP 会话存储

我最近有机会将一个 Web 应用程序从使用 Nginx 代理“负载均衡器”迁移到使用 F5 负载均衡器。不幸的是,在迁移过程中,很明显memcached需要将会话存储从 Nginx 代理服务器移动到“某个地方”。我的想法是,我应该memcached在所有 3 个 Web 服务器(位于池中 F5 后面的服务器)上安装并使用php-memcachephp-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 使用这种技术,因此任何服务器都可以回答任何用户请求,即使用户会话在另一个数据中心启动。

相关内容