如何在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

lamp02lamp03 上重复这些步骤。

第四步 - 测试会话冗余

要测试此设置,请在所有 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 池中的云服务器相互通信。

我们在测试会话冗余之后执行此步骤,以便更容易解决如果应用不正确的规则可能出现的问题。

使用 lamp02lamp03 的私有 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

使用 lamp01lamp03 的私有 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 上使用 lamp01lamp02 的私有 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 中的测试,以确认防火墙没有阻止我们的流量。

附加阅读