如何在Ubuntu14.04上的多个Memcached服务器上共享PHP会话
介绍
Memcached 是一个分布式对象缓存系统,它将信息存储在内存中,而不是磁盘上,以便更快地访问。 PHP 的 Memcache 模块可用于处理原本会存储在文件系统中的会话。 在 Memcached 中存储 PHP 会话的优点是能够将它们分发到运行 Memcached 的多个云服务器上,从而保持会话冗余。
如果没有此 Memcached 设置,如果您的应用程序在多个服务器上进行负载平衡,则有必要在负载平衡器上配置会话粘性。 这可以维护用户体验并防止他们突然被注销。 将 Memcached 配置为处理会话将确保 Memcached 池中的所有云服务器具有相同的会话数据集,从而无需粘在一台服务器上来保留会话。
先决条件
本教程假设您熟悉 在 Ubuntu 中设置 LAMP 服务器。 此设置将使用带有 Ubuntu 14.04 映像的 3 个 Droplet。
液滴 1
- 名称:灯01
- 公共IP:1.1.1.1
- 私有IP:10.1.1.1
液滴 2
- 名称:灯02
- 公共IP:2.2.2.2
- 私有IP:10.2.2.2
液滴 3
- 名称:灯03
- 公共IP:3.3.3.3
- 私有IP:10.3.3.3
确保在创建 Droplet 时勾选了 Private Networking 复选框。 此外,请记下私有 IP 地址,因为我们稍后将需要它们。
在所有三台服务器上安装 LAMP。
首先,更新存储库并安装 Apache。
apt-get update apt-get install apache2
安装 PHP 和 Apache 的 mod_php 扩展。
apt-get install php5 libapache2-mod-php5 php5-mcrypt
有关详细信息,请参阅这篇文章。
第一步 - 安装 Memcache 包
在 lamp01 上,安装 Memcached 守护进程和 PHP 的 Memcache 模块。
apt-get install php5-memcache memcached
PHP 有两个包:php5-memcache 和 php5-memcached(注意末尾的“d”)。 我们将使用第一个包(memcache),因为它更轻,没有任何依赖关系。 阅读 memcache 和 memcached 之间的比较。
Memcached 服务仅侦听 localhost (127.0.0.1)。 必须将其更改为接受来自专用网络的连接。
nano /etc/memcached.conf
找到以下行:
-l 127.0.0.1
将其更改为侦听此服务器的私有 IP 地址。
-l 10.1.1.1
重启memcached
服务。
service memcached restart
在其他两台服务器上重复这些步骤,将 127.0.0.1
替换为适当的私有 IP 地址。
灯02
-l 10.2.2.2
灯03
-l 10.3.3.3
重启后两台服务器的memcached
服务。
第二步 - 将 Memcache 设置为 PHP 的 Session Handler
在 lamp01 上,打开 php.ini
文件进行编辑。
nano /etc/php5/apache2/php.ini
该文件位于 PHP-FPM 安装的 /etc/php5/fpm/php.ini
中。
找到以下配置指令:
session.save_handler = session.save_path =
修改它们以使用 Memcache,如下所示。 使用 session.save_path
中的所有三个私有 IP 地址。
session.save_handler = memcache session.save_path = 'tcp://10.1.1.1:11211,tcp://10.2.2.2:11211,tcp://10.3.3.3:11211'
您可能需要通过删除开头的分号来取消注释 session.save_path
。 请记住在每个 IP 地址后输入端口号 11211,因为 Memcached 会侦听此端口。
在其他两台服务器上添加完全相同的设置。
在 lamp02 上:
session.save_handler = memcache session.save_path = 'tcp://10.1.1.1:11211,tcp://10.2.2.2:11211,tcp://10.3.3.3:11211'
在 lamp03 上:
session.save_handler = memcache session.save_path = 'tcp://10.1.1.1:11211,tcp://10.2.2.2:11211,tcp://10.3.3.3:11211'
此配置在所有 Droplet 上必须完全相同,会话共享才能正常工作。
第三步 - 为会话冗余配置 Memcache
在 lamp01 上,编辑 memcache.ini
文件。
nano /etc/php5/mods-available/memcache.ini
将以下配置指令添加到此文件的末尾。
memcache.allow_failover=1 memcache.session_redundancy=4
memcache.session_redundancy
指令必须等于 memcached 服务器的数量 + 1,以便将会话信息复制到所有服务器。 这是由于 PHP 中的 错误造成的。
这些指令启用会话故障转移和冗余,因此 PHP 将会话信息写入 session.save_path
中指定的所有服务器; 类似于 RAID-1 设置。
根据正在使用的内容重新启动 Web 服务器或 PHP FPM 守护程序。
service apache2 reload
在 lamp02 和 lamp03 上重复这些步骤。
第四步 - 测试会话冗余
要测试此设置,请在所有 Droplet 上创建以下 PHP 脚本。
/var/www/html/session.php
<?php header('Content-Type: text/plain'); session_start(); if(!isset($_SESSION['visit'])) { echo "This is the first time you're visiting this server\n"; $_SESSION['visit'] = 0; } else echo "Your number of visits: ".$_SESSION['visit'] . "\n"; $_SESSION['visit']++; echo "Server IP: ".$_SERVER['SERVER_ADDR'] . "\n"; echo "Client IP: ".$_SERVER['REMOTE_ADDR'] . "\n"; print_r($_COOKIE); ?>
此脚本仅用于测试,一旦设置了 Droplets,就可以将其删除。
使用 curl 在第一个 Droplet 上访问此文件并提取 cookie 信息。
curl -v -s http://1.1.1.1/session.php 2>&1 | grep 'Set-Cookie:'
这将返回类似于以下内容的输出。
< Set-Cookie: PHPSESSID=8lebte2dnqegtp1q3v9pau08k4; path=/
复制 PHPSESSID
cookie 并使用此 cookie 将请求发送到其他 Droplet。 如果在 1440 秒内没有任何请求,PHP 将删除此会话,因此请确保在此时间范围内完成测试。 阅读 PHP 的 session.gc-maxlifetime 以了解更多信息。
curl --cookie "PHPSESSID=8lebte2dnqegtp1q3v9pau08k4" http://1.1.1.1/session.php http://2.2.2.2/session.php http://3.3.3.3/session.php
您会发现会话正在跨所有 Droplet 进行。
Your number of visits: 1 Server IP: 1.1.1.1 Client IP: 117.193.121.130 Array ( [PHPSESSID] => 8lebte2dnqegtp1q3v9pau08k4 ) Your number of visits: 2 Server IP: 2.2.2.2 Client IP: 117.193.121.130 Array ( [PHPSESSID] => 8lebte2dnqegtp1q3v9pau08k4 ) Your number of visits: 3 Server IP: 3.3.3.3 Client IP: 117.193.121.130 Array ( [PHPSESSID] => 8lebte2dnqegtp1q3v9pau08k4 )
要测试故障转移,请停止 memcached
服务并在其上访问此文件。
service memcached stop
Droplet 透明地使用存储在其他两个服务器上的会话信息。
curl --cookie "PHPSESSID=8lebte2dnqegtp1q3v9pau08k4" http://1.1.1.1/session.php
输出:
Your number of visits: 4 Server IP: 1.1.1.1 Client IP: 117.193.121.130 Array ( [PHPSESSID] => 8lebte2dnqegtp1q3v9pau08k4 )
现在可以将负载均衡器配置为均匀分配请求,而无需配置会话粘性。
完成测试后再次启动 memcached
:
service memcached start
第五步 - 使用 IPTables 保护 Memcached
即使 Memcached 使用的是私有网络,如果同一数据中心的其他 DigitalOcean 用户知道您的私有 IP,他们也可以连接到您的 Droplet。 因此,我们将 设置 IPTables 规则 以仅允许我们的 Memcached 池中的云服务器相互通信。
我们在测试会话冗余之后执行此步骤,以便更容易解决如果应用不正确的规则可能出现的问题。
使用 lamp02 和 lamp03 的私有 IP 地址在 lamp01 上创建防火墙规则。
iptables -A INPUT -s 10.2.2.2 -i eth1 -p tcp -m state --state NEW -m tcp --dport 11211 -j ACCEPT iptables -A INPUT -s 10.3.3.3 -i eth1 -p tcp -m state --state NEW -m tcp --dport 11211 -j ACCEPT
在典型的 LAMP 服务器上,以下是完整的规则集:
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT iptables -A INPUT -s 10.2.2.2 -i eth1 -p tcp -m state --state NEW -m tcp --dport 11211 -j ACCEPT iptables -A INPUT -s 10.3.3.3 -i eth1 -p tcp -m state --state NEW -m tcp --dport 11211 -j ACCEPT iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT iptables -P INPUT DROP
使用 lamp01 和 lamp03 的私有 IP 地址在 lamp02 上输入防火墙规则。
iptables -A INPUT -s 10.1.1.1 -i eth1 -p tcp -m state --state NEW -m tcp --dport 11211 -j ACCEPT iptables -A INPUT -s 10.3.3.3 -i eth1 -p tcp -m state --state NEW -m tcp --dport 11211 -j ACCEPT
在 lamp03 上使用 lamp01 和 lamp02 的私有 IP 地址执行相同操作。
iptables -A INPUT -s 10.1.1.1 -i eth1 -p tcp -m state --state NEW -m tcp --dport 11211 -j ACCEPT iptables -A INPUT -s 10.2.2.2 -i eth1 -p tcp -m state --state NEW -m tcp --dport 11211 -j ACCEPT
重复 步骤 4 中的测试,以确认防火墙没有阻止我们的流量。