PHP сессии в кластере балансировки нагрузки - как? - PullRequest
45 голосов
/ 15 июня 2009

ОК, так что у меня есть совершенно редкий уникальный сценарий PHP-сайта с балансировкой нагрузки. Облом - это раньше не было с балансировкой нагрузки. Теперь у нас начинаются проблемы ...

В настоящее время единственная проблема связана с сессиями PHP. Естественно, никто не задумывался об этой проблеме вначале, поэтому конфигурация сеанса PHP оставалась с настройками по умолчанию. Таким образом, оба сервера имеют свой собственный небольшой набор файлов сеансов, и горе - это пользователь, который получает следующий запрос на другой сервер, потому что у него нет сеанса, который он создал на первом.

Теперь я читаю руководство по PHP, как решить эту ситуацию. Там я нашел замечательную функцию session_set_save_handler(). (И, по совпадению, эта тема на SO) Аккуратно. За исключением того, что мне придется вызывать эту функцию на всех страницах сайта. И разработчики будущих страниц должны были бы не забывать называть это также все время. Чувствует себя немного неуклюже, не говоря уже о том, что, вероятно, нарушает дюжину лучших практик кодирования. Было бы гораздо приятнее, если бы я просто включил какой-нибудь глобальный параметр конфигурации и Voilà - все сеансы волшебным образом хранятся в БД, кеше памяти или чем-то подобном.

Есть идеи, как это сделать?


Добавлено: Для пояснения - я ожидаю, что это будет стандартная ситуация со стандартным решением. К вашему сведению - у меня есть MySQL DB. Конечно, должен быть какой-нибудь готовый к использованию код, который решает эту проблему? Конечно, я могу написать свой собственный материал для сохранения сеанса, и вариант auto_prepend, на который указывает Грег , выглядит многообещающим, но это будет похоже на изобретение колеса. :П
Добавлено 2: Балансировка нагрузки основана на DNS. Я не уверен, как это работает, но я думаю, это должно быть что-то вроде this .
Добавлено 3: ОК, я вижу, что одним из решений является использование опции auto_prepend для вставки вызова в session_set_save_handler() в каждом скрипте и записи моего собственного БД в персистентном виде, возможно, для вызова memcached для лучшая производительность. Достаточно справедливо.

Есть ли какой-нибудь способ, которым я мог бы избежать всего этого сам? Как какой-то известный и проверенный плагин PHP?

Добавлено намного, намного позже: В конце концов, я так и сделал: Как правильно реализовать сохранение персистентной сессии в PHP + MySQL?

Кроме того, я просто включил обработчик сеанса вручную на всех страницах.

Ответы [ 10 ]

32 голосов
/ 15 июня 2009

Вы можете настроить PHP для обработки сеансов в базе данных, поэтому все ваши серверы совместно используют одну и ту же информацию о сеансах, поскольку все серверы используют для этого одну и ту же базу данных.

Хороший учебник для этого можно найти здесь .

20 голосов
/ 24 октября 2012

То, как мы справляемся с этим, - через memcached. Все, что нужно, это изменить php.ini, как показано ниже:

session.save_handler = memcache
session.save_path = "tcp://path.to.memcached.server:11211"

Мы используем AWS ElastiCache, поэтому путь к серверу является доменом, но я уверен, что он будет аналогичным и для локальной memcached.

Этот метод не требует изменений кода приложения.

7 голосов
/ 15 июня 2009

Вы не упомянули, какую технологию вы используете для балансировки нагрузки (программное обеспечение, оборудование и т. Д.); но в любом случае решение вашей проблемы - использовать «липкие сессии» на балансировщике нагрузки.

Таким образом, это означает, что когда поступает первый запрос от «нового» посетителя, ему назначается конкретный сервер из кластера: все последующие запросы на время жизни их сеанса затем направляются на этот сервер. На практике это означает, что приложения, написанные для работы на одном сервере, можно масштабировать до сбалансированной среды с нулевым / небольшим количеством изменений кода.

Если вы используете аппаратный балансировщик, такой как устройство Radware, то липкие сеансы настраиваются как часть настройки кластера. Аппаратные устройства обычно дают вам более детальный контроль: например, серверу, которому назначен новый пользователь (они могут проверить состояние работоспособности и т. Д. И выбрать наиболее работоспособный / наименее используемый сервер), а также лучше контролировать то, что происходит, когда сервер выходит из строя и выпадает из кластера. Недостатком аппаратных балансировщиков является стоимость, но они того стоят.

Что касается программных балансировщиков, все сводится к тому, что вы используете. Для Apache есть свойство stickysession в mod_proxy - и множество статей через google, чтобы это работало с сеансом php ( например )


Edit: Из других комментариев, опубликованных после исходного вопроса, похоже, что ваша «балансировка» осуществляется через Round Robin DNS, поэтому вышеприведенное, вероятно, не будет применяться. Я воздержусь от дальнейших комментариев и запуска пламени против круглых робин днс.

4 голосов
/ 13 июля 2013

Если у вас есть время и вы все еще хотите проверить больше решений, взгляните на http://redis4you.com/articles.php?id=01..

Используя redis, вы отказоустойчивы. С моей точки зрения, это может быть лучше, чем решения memcache из-за этой надежности.

3 голосов
/ 15 июня 2009

Самое простое - настроить балансировщик нагрузки так, чтобы он всегда отправлял один и тот же сеанс на один и тот же сервер.

Если вы все еще хотите использовать session_set_save_handler, то, возможно, посмотрите на auto_prepend.

2 голосов
/ 15 июня 2009

Если вы используете сеансы php, вы можете поделиться с NFS каталогом / tmp, где, как мне кажется, сессии хранятся, между всеми серверами в кластере. Таким образом, вам не нужна база данных.

Отредактировано: Вы также можете использовать внешний сервис, такой как memcachedb (постоянный и быстрый), и сохранить информацию о сеансе в индексе memcachedb и идентифицировать ее с помощью хеша содержимого или даже идентификатора сеанса.

2 голосов
/ 15 июня 2009

вы также можете попробовать использовать memcache в качестве обработчика сессии

2 голосов
/ 15 июня 2009

Когда у нас возникла такая ситуация, мы реализовали некоторый код, который живет в общем заголовке.

По существу для каждой страницы мы проверяем, знаем ли мы идентификатор сессии. Если мы не проверяем, находимся ли мы в ситуации, которую вы описываете, проверяя, сохранили ли мы данные сеанса в БД. В противном случае мы просто начинаем новый сеанс.

Очевидно, что для этого необходимо скопировать все соответствующие данные в БД, но если вы инкапсулируете данные своего сеанса в отдельный класс, тогда все будет хорошо.

1 голос
/ 03 декабря 2013

Возможно, уже слишком поздно, но проверьте это: http://www.pureftpd.org/project/sharedance

Sharedance - это высокопроизводительный сервер для централизации эфемерного ключа / данных. пары на удаленных хостах, без накладных расходов и сложности SQL базы данных.

Он был в основном предназначен для совместного использования кэшей и сеансов между пулом сети сервера. Доступ к серверу общего доступа тривиален с помощью простого PHP API и он совместим с ожиданиями обработчиков сеансов PHP 4 и PHP 5.

0 голосов
/ 13 января 2017

Когда дело доходит до обработки php-сессии в кластере балансировки нагрузки, лучше всего использовать Sticky Sessions. Для этого спросите сеть центра обработки данных, который поддерживает балансировщик нагрузки, чтобы включить липкий сеанс. Как только это будет включено, вам не нужно беспокоиться о сессиях в конце php

...