Распределение PHP-сессий в Memcached (Ubuntu 14.04)

Memcached – распределенная система кэширования объектов, для более быстрого доступа хранящая информацию в памяти, а не на диске. РНР-модуль Memcache может быть использован для обработки сессий (которые в противном случае будут храниться в файловой системе). Хранение PHP-сессий в Memcached имеет существенное преимущество – это возможность распределять сессии на несколько облачных серверов, на которых также запущен Memcached.

Благодаря обработке сессий в Memcached все облачные серверы кластера Memcached будут иметь одинаковый набор данных сессии, что исключает необходимость привязки (или stickiness) серверов для сохранения сессий.

Требования

Предполагается, что пользователь знаком с установкой LAMP в Ubuntu.

В данном руководстве используется 3 сервера Ubuntu 14.04:

Сервер 1

  • Имя: lamp01
  • Общественный IP: 01.01.1.1
  • Персональный IP: 10.1.1.1

Сервер 2

  • Имя: lamp02
  • Общественный IP: 02.02.2.2
  • Персональный IP: 10.2.2.2

Сервер 3

  • Имя: lamp03
  • Общественный IP: 03.03.3.3
  • Персональный IP: 10.3.3.3

Убедитесь, что при создании серверов флаговая кнопка 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

Чтобы получить подробные инструкции, читайте руководство «Установка LAMP stack на Ubuntu 14.04».

1: Установка пакетов Memcache

На сервере lamp01 установите демон Memcached и PHP-модуль Memcache.

apt-get install php5-memcache memcached

PHP имеет два пакета: php5-memcache и php5-memcached (обратите внимание на «d» в конце). В данном руководстве будет использоваться первый пакет, php5-memcache, поскольку он занимает меньше места и не имеет зависимостей. Чтобы узнать об остальных различиях данных пакетов, перейдите по данной ссылке.

Сервис Memcached прослушивает только локальный хост (127.0.0.1). Чтобы принимать соединения частной сети, это нужно изменить. Откройте конфигурационный файл:

nano /etc/memcached.conf

Найдите следующую строку:

-l 127.0.0.1

Замените локальный хост (127.0.0.1) персональным IP-адресом сервера lamp01 (10.1.1.1).

-l 10.1.1.1

Перезапустите сервис memcached.

service memcached restart

Выполните эти инструкции на остальных серверах, заменив локальный хост соответствующим персональным IP-адресом сервера:

lamp02

-l 10.2.2.2

lamp03

-l 10.3.3.3

Не забудьте перезапустить сервис memcached на остальных серверах.

2: Memcache как обработчик PHP-сессий

Откройте и отредактируйте файл php.ini на сервере lamp01:

nano /etc/php5/apache2/php.ini

Данный файл находится в /etc/php5/fpm/php.ini в инсталляции PHP-FPM.

Найдите следующие директивы:

session.save_handler =
session.save_path =

Отредактируйте их следующим образом, чтобы PHP использовал 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 понадобится раскомментировать, удалив символ токи с запятой в начале строки.

Примечание: не забудьте ввести номер порта 11211 после каждого IP-адреса, поскольку 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'

3: Настройка избыточного хранения сессий

Отредактируйте файл memcache.ini на сервере lamp01:

nano /etc/php5/mods-available/memcache.ini

Внесите следующие директивы в конец файла:

memcache.allow_failover=1
memcache.session_redundancy=2

Данные директивы активируют переключение (failover) и избыточное хранение (redundancy) сессий; таким образом, PHP записывает сессии на все серверы, указанные в session.save_path.

Перезапустите веб-сервер или PHP FPM (в зависимости от того, какая из программ используется):

service apache2 reload

Повторите эти действия на lamp02 и lamp03.

4: Тестирование избыточного хранения сессий

Чтобы проверить данную настройку, нужно создать на всех серверах кластера следующий 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);
?>

Данный скрипт предназначен исключительно для тестирования, его можно удалить сразу после выполнения проверки.

Откройте данный файл на первом сервере и запросите информацию о cookie:

curl -v -s http://01.01.1.1/session.php 2>&1 | grep 'Set-Cookie:'

Это выведет подобный результат:

< Set-Cookie: PHPSESSID=8lebte2dnqegtp1q3v9pau08k4; path=/

Скопируйте PHPSESSID cookie и отправьте с его помощью запрос остальным серверам.

Примечание: PHP удалит данную сессию, если в течение 1440 секунд не будет отправлено никаких запросов, поэтому постарайтесь вложиться в эти сроки. Получить больше информации о 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

Как видите, данная сессия протекает на всех серверах кластера:

Your number of visits: 1
Server IP: 01.01.1.1
Client IP: 117.193.121.130
Array
(
[PHPSESSID] => 8lebte2dnqegtp1q3v9pau08k4
)
Your number of visits: 2
Server IP: 02.02.2.2
Client IP: 117.193.121.130
Array
(
[PHPSESSID] => 8lebte2dnqegtp1q3v9pau08k4
)
Your number of visits: 3
Server IP: 03.03.3.3
Client IP: 117.193.121.130
Array
(
[PHPSESSID] => 8lebte2dnqegtp1q3v9pau08k4
)

Чтобы протестировать переключение, остановите сервис memcached и откройте следующий файл:

service memcached stop

Теперь сервер использует информацию о сессии, которая хранится на двух других серверах.

curl --cookie "PHPSESSID=8lebte2dnqegtp1q3v9pau08k4" http://01.01.1.1/session.php

Результат:

Your number of visits: 4
Server IP: 1.1.1.1
Client IP: 117.193.121.130
Array
(
[PHPSESSID] => 8lebte2dnqegtp1q3v9pau08k4
)

Теперь балансировщик нагрузки можно настроить для равномерного распределения запросов и при этом не тратить время на настройку привязки (или stickiness) серверов.

Завершив проверку, снова запустите memcached:

service memcached start

5: Защита Memcached при помощи IPTables

Даже при наличии частной сети другие пользователи могут подключиться к вашему серверу, если они знают его персональный IP-адрес. Но это можно предотвратить, настроив правила IPTables, разрешающие серверам кластера Memcached взаимодействовать только друг с другом.

Поскольку избыточное хранение сессий уже протестировано, будет легче устранить проблемы, которые могут возникнуть при установке некорректных правил.

Создайте правила брандмауэра lamp01, внеся персональные IP-адреса lamp02 и lamp03.

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

Затем создайте правила фаервола lamp02, в этот раз используя персональные IP серверов lamp01 и 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.3.3.3 -i eth1 -p tcp -m state --state NEW -m tcp --dport 11211 -j ACCEPT

Далее нужно создать правила брандмауэра lamp03 с указанием персональных IP-адресов серверов lamp01 и 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.2.2.2 -i eth1 -p tcp -m state --state NEW -m tcp --dport 11211 -j ACCEPT

Установив правила на каждом сервере, повторите действия раздела 4, чтобы убедиться, что брандмауэр не блокирует серверы данного кластера (в противном случае в правилах допущена ошибка).

Tags: , , , , , , , , ,

Добавить комментарий