介绍
Memcached是一个分布式对象缓存系统,它将信息存储在内存中,而不是存储在磁盘上,以便更快地访问。 PHP的Memcache模块可用于处理会话,否则会存储在文件系统上。 在Memcached中存储PHP会话具有能够将其分发到运行Memcached的多个云服务器的优点,从而保持会话冗余。
如果没有此Memcached设置,如果您的应用程序在多个服务器上进行负载平衡,则有必要在负载均衡器上配置会话粘性。 这保持了用户体验,并防止他们突然注销。 配置Memcached以处理会话将确保Memcached池中的所有云服务器具有相同的会话数据集,从而无需使用一个服务器保持会话。
先决条件
本教程假定您熟悉Ubuntu中设置LAMP服务器 。
这样的设置将利用3Droplet与Ubuntu的14.04图像。
Droplet1
- 名称:lamp01
- 公共IP:1.1.1.1
- 私人IP:10.1.1.1
Droplet2
- 名称:lamp02
- 公共IP:2.2.2.2
- 私人IP:10.2.2.2
Droplet3
- 名称:lamp03
- 公共IP:3.3.3.3
- 私人IP:10.3.3.3
确保专用网络建立Droplet时复选框被选中。 另外,请记下私有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的内存缓存模块。
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地址。
lamp02
-l 10.2.2.2
lamp03
-l 10.3.3.3
重新启动memcached
第二两个服务器上的服务。
第二步 - 将Memcache设置为PHP的会话处理程序
在lamp01,打开php.ini
文件进行编辑。
nano /etc/php5/apache2/php.ini
该文件位于/etc/php5/fpm/php.ini
对PHP-FPM安装。
查找以下配置指令:
session.save_handler =
session.save_path =
修改它们以使用Memcache,如下所示。 使用所有这三个私有IP地址的session.save_path
。
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'
此配置必须在所有Droplets上完全相同,以便会话共享正常工作。
第三步 - 配置会话冗余的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);
?>
此脚本仅用于测试,可在设置Droplet后删除。
在第一个Droplet上使用curl访问此文件,并提取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用户也可以连接到您的Droplet,如果他们知道您的私有IP。 因此,我们将建立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
不要与lamp01和lamp02的私有IP地址lamp03相同。
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步中的测试,以确认防火墙没有阻止我们的交通。