Labutin
@Labutin
Web-разработчик

PHP Cluster и файлы сессий на общем файловом хранилище. Возникают бесконечные блокировки

Имеющееся хозяйство:
— Два PHP сервера
— Балансировщик
— Файловое хранилище, подключенное к обоим серверам по iSCSI. Файловая система OCFS2.
Схема PHP кластера тривиальна — балансировщик в соответствии со своей логикой переправляет каждый запрос на один из PHP серверов. Запросы одного и того же пользователя могут уйти на разные сервера. Сразу скажу, что параметр аля ip_hash в nginx нам не подходит и всегда есть вероятность, что запрос пользователя уйдет на другой PHP сервер. Как следствие, нам нужны общие сессии на обоих PHP серверах.
Дальше гуглятся в 99% случаев два решения:
— сессии в базе данных
— сессии в memcached
Добавляю еще одно требование — да, нам жизненно важна блокировка сессий (при хранении сессий в файлах она есть по умолчанию) и переписать проект совсем не тривиальная задача. memcached уже отпадает, т.к. там нет блокировок (или что-то изменилось?). И еще нам важно сохранение сессий при ребуте серверов. Тем более чистый вариант с memcached не подходит. Читал про гибриды — memcached с регулярным сбрасыванием сессий в MySQL. Думаем над этим решением.

Но мы решили хранить сессии на общем файловом хранилище. Ведь оно есть. И оно общее. И сессии там блокируются (проверено, работает).
Но есть одно огромное НО! Под реальной нагрузкой не сразу, но через несколько минут вдруг все PHP процессы на обоих серверах встают на ожидании разблокировки сессии. Стоит один из PHP серверов вывести из игры, как на втором все разблокируется и он весело в одно лицо обслуживает клиентов.

Собственно вопрос: есть у кого реальный опыт хранение сессий именно на общем файловом хранилище? У вас подобная проблема возникала? Как решали? Может быть мы в принципе что-то делаем не так?

P.S.
Oracle Linux Server release 6.4
Linux php01-dc 2.6.39-400.21.1.el6uek.x86_64 #1 SMP Thu Apr 4 03:49:00 PDT 2013 x86_64 x86_64 x86_64 GNU/Linux
nginx + php-fpm
PHP Version 5.3.23
Статистика запросов (5-10 запросов в секунду — это именно обращения к PHP скриптам)
  • Вопрос задан
  • 4304 просмотра
Пригласить эксперта
Ответы на вопрос 8
Mendel
@Mendel
PHP-developer
Не хочется говорить банальные вещи, но ИМХО необходимость блокировки сессий и при этом отказ от привязки ip пользователя к конкретному серверу это признак ошибки в архитектуре.

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

Вообще странно, что при такой нагрузке у вас возникают проблемы. Каково количество сессий в момент блокировки?

Как вы работаете с сессиями? Стандартный обработчик, или таки что-то свое в session_set_save_handler, но тоже работающее с файлами?

Есть стойкое ощущение, что сессия по каким-то причинам не освобождается. Может быть поможет register_shutdown_function('session_write_close'); Хотя я так и не понял из документации какой в этом смысл, но зачем-то session_register_shutdown было придумано…

Еще я бы на вашем месте покурил www.php.net/manual/ru/function.session-write-close.php, а точнее комментарии к ней. ИМХО там описано пару кейсов которые могут оказаться вашими.

Один раз я встретил очень забавный случай, который приводил к проблемам с сессиями на относительно небольшой нагрузке — в одном проекте сессии инициировались не только там где было уместно, но и даже в статики. Про генерируемые картинки, которым сессии были вообще не нужны я вообще молчу…

Попробуйте в session_set_save_handler сделать логирование открытий/закрытий, уничтожений вызовов мусорщика и т.п. Может быть это даст вам ключ к пониманию проблемы.

В любом случае я бы вам советовал уходить в базу. Это более масштабируемо, управляемо и т.п. Я конечно понимаю, что транзакции в сессиях это перебор, но мы пока так и не увидели ваш кейс, может быть когда будут детали удастся что-то лучше придумать.
Ответ написан
@unity_ultra_hardcore
Лучше расскажите, что за такая извращённая задача, где потребовались блокировки сессий?
Ответ написан
dizballanze
@dizballanze
Software developer at Yandex
Почему не использовать memcached или redis для хранения сессий?
Ответ написан
@edogs
Сессии блокируются индивидуально под каждого юзера, поэтому ситуация «висит абсолютно все и ждет» очень необычна.
Учитывая что у Вас iSCSI, более логичным было бы предположение о том, что кончился лимит на кол-во коннектов с файлохранилищу по tcp/ip, и поэтому все висит — т.к. ждет пока свободные коннекты освободятся. Проверьте эту версию. Если она верна, то скорее всего по какой-то причине не рвется (или не всегда рвется) коннект после отработки пхп скрипта и они накапливаются.
Быстрый фикс — сбрасывать долго висящие соединения или увеличить лимит на их количество. Долгий — разобраться почему не рвутся и пофиксить.
Похожая проблема иногда возникает с persistent соединениями с базой или с мемкешем, поэтому их использовать стремно в реальных проектах, хотя теоретически они круты.
Ответ написан
EugeneOZ
@EugeneOZ
«Но мы решили хранить сессии на общем файловом хранилище.»
И тут наступил пиз... коллапс. Это самое плохое решение, которое вы могли принять.

Почитал комменты вашего представителя здесь: habrahabr.ru/company/bitrix/blog/179803/ — ппц. Назвать Redis тяжёлым и «слоном» может только тот, кто НИКОГДА его не использовал и даже сравнения бенчмарков не смотрел.
Проблема в головах у вас, а не в блокировке сессий. Поэтому нужно начинать с подсматривания, как сделано в крупных проектах и фреймворках, потом почитать десяток статей на эту тему, попробовать новые инструменты, а потом уже пробовать рефакторить код.
Сорри, если грубо, просто выглядит ваш текст бредово. Ничего личного.

Кстати, "— Файловое хранилище, подключенное к обоим серверам по iSCSI. Файловая система OCFS2." — этот момент тоже вам аукнется в будущем.
Ответ написан
@egorinsk
У вас как-то странно сделана блокировка. Сессии должны блокироваться индивидуально, и сессия одного пользователя никак не влияет на других (или у вас все пользователи используют одну общую сессию?). У вас что-то неправильно работает.
Ответ написан
@Vampiro
В порядке бреда: Может на серверах php-fpm от разных пользователей запущены? И тогда права на файл с сессией созданой серв№1 не позволяют в нее записать с серв№2?
Ответ написан
@mayorovp
Что-то я не могу, как можно заблокировать ФАЙЛ по ISCSI. Похоже, что блокируется не файл, а часть хранилища. Взаимоблокировка случается, когда файл сессии пересекает границы подлежащих блокировке блоков.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
ЧИТАЙ-ГОРОД Москва
от 140 000 до 210 000 ₽
Modens Group Москва
от 100 000 до 150 000 ₽
Mediapark Group Калининград
от 100 000 ₽
18 февр. 2020, в 23:53
8000 руб./за проект
18 февр. 2020, в 22:14
10000 руб./за проект