Сессии PHP в кластере балансировки нагрузки – как?

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

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

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

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


Добавлено: уточнить – я ожидаю, что это будет стандартная ситуация со стандартным решением. FYI. У меня есть MySQL DB. Наверняка должен быть какой-то готовый к использованию код, который решает это? Я могу, конечно, написать собственный материал для сохранения сеанса, а опция auto_prepend Грегом, кажется многообещающей – но это будет похоже на повторное использование колеса. :П


Добавлено 2: Балансировка нагрузки основана на DNS. Я не уверен, как это работает, но я думаю, что это должно быть что-то вроде этого .


Добавлено 3: ОК, я вижу, что одним из решений является использование опции auto_prepend для вставки вызова в session_set_save_handler() в каждом скрипте и записи моего собственного БД-персистента, возможно, с вызовом memcached для повышения производительности. Справедливо.

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

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

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

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

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

То, как мы справляемся с этим, – это memcached. Все, что требуется, это изменение php.ini, похожее на следующее:

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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