Блокировка php сессий wordpress

Блокировки сессий в PHP и их отладка

Буквально несколько дней назад на сайте 1С-Битрикс была опубликована статья Николая Рыжонина о возможностях сократить случаи блокировки сессий для долгих обработок запросов. Мы же в своей статье решили в целом пройтись подробнее — почему эти блокировки происходят, почему PHP-процессы «залипают» на инициализации сессий — session_start() — и как с этим бороться.

Время от времени у наших клиентов в процессе отладки запросов, которые долго выполняются, возникает вопрос — почему сессии начинают долго работать? Выглядит проблема примерно так — неожиданно пользователь, пытаясь открывать новые страницы на сайте, не может дождаться их открытия, а если пользователь генерирует большое число таких запросов, это происходит уже у всех посетителей сайта. Apache/PHP-FPM забиваются процессами, ожидающими снятия блокировки с файла сессий, и часто — помогает только перезапуск этих сервисов.

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

Стандартный обработчик сессий в PHP реализует их хранение в файлах путем хранения сериализованного содержимого массива $_SESSION в файле в директории, заданной переменной session.save_path. При старте сессии функцией session_start PHP либо создает и открывает, либо повторно открывает файл сессии. При этом PHP выставляет глобальную блокировку на чтение этого файла на время работы с ним. Сделано это преднамеренно — в противном случае в условиях многопоточности несколько скриптов могут открыть один и тот же файл с сессией, изменить значения ее переменных, а затем закрыть и записать сессию в файл, и таким образом данные одного из скриптов будут утеряны.
Объяснить это можно простым примером: пусть есть скрипты 1.php и 2.php и некая сессия в которой уже выставлены следующие переменные:

$_SESSION['aaa']='111'; $_SESSION['bbb']='222'; $_SESSION['ccc']='333';

Если бы в PHP не была реализована блокировка сессий, а скрипты выполнились бы одновременно, результаты выполнения работы скрипта 1.php не были бы сохранены в сессии.

Все это в принципе приемлемо, до той поры, пока скрипты выполняются несколько сотен миллисекунд (что типично для веба), однако активное использование AJAX-а, активная разработка, сложные внутренние портальные системы создают большой риск для длительной блокировки сессий, источник которой приходится довольно нетривиально ловить.

Для примера — довольно часто мы видим, как некие сложные процессы, выполнение которых занимает длительное время, реализуют через AJAX-запрос. Пользователь заходит на страницу, где запускает, например, процесс импорта данных из внешнего сервиса. Импорт происходит в скрипте, через AJAX-запрос. Пока импорт происходит, пользователь может открыть и другие страницы. Если вдруг работа внешнего сервиса замедляется, а скрипт, занимающийся импортом использует сессии — файл сессий останется заблокированным на время выполнения этого скрипта. Соответственно ни одна страница сайта для этого пользователя не будет открыта до завершения его работы. Скрипт выполняется десятки секунд? Все это время сайт будет полностью недоступен для пользователя.

Читайте также:  Java mockito call real method

Ловить подобную проблему, если она начинает происходить массово, очень сложно. Если мы решим просто отследить, где висят запросы пользователя — большая часть запросов окажется висящими в состоянии session_start() — раздраженные пользователи пытаются снова и снова открыть недоступные страницы. Для того, чтобы ловить подобныю проблемы, мы рекомендуем использовать профилирующий модуль XHProf от фейсбука с последующей фильтрацией результатов его работы. XHProf сохраняет результаты работы в файл с сериализованным массивом статистики, который потом сам же использует для профилировки. Таким образом мы получаем набор файлов с результатами выполнения каждого запроса пользователя. Для того чтобы выбрать нужные нам результаты, необходимо открыть каждый файл и проверить, какое время выполнения занимала функция session_start() — нас интересуют только те, где выполнения скрипта было долгим, а выполнение этой функции — коротким, те самые скрипты, которые привели к блокировке. Мы для фильтрации используем следующий скрипт:

Источник

Блокировка сессии в PHP

Технология сессии в PHP являются простым способом хранения информации для отдельно взятого пользователя сайта. Например: товары, добавленные в корзину магазина, настройки уведомлений и т.д. При первом запросе сайта к серверу, в браузере сохраняется в cookies уникальный идентификатор сессии пользователя. Затем идентификатор или связка идентификатора с IP адресом идентифицирует пользователя. Это может использоваться для сохранения состояния между запросами страниц. Идентификаторы сессий обычно отправляются браузеру через сессионный Cookie и используются для получения имеющихся данных сессии.

Сессии используют простую технологию: PHP будет либо получать данные существующей сессии, используя переданный идентификатор (обычно из сессионного cookie), или, если ничего не передавалось, будет создана новая сессия. PHP заполнит суперглобальную переменную $_SESSION сессионной информацией после того, как будет запущена сессия. Когда PHP завершает работу, он автоматически сериализует содержимое суперглобальной переменной $_SESSION и отправляет для сохранения, используя сессионный обработчик для записи сессии.

По умолчанию PHP использует внутренний обработчик files для сохранения сессий, который установлен в INI-переменной session.save_handler. Этот обработчик сохраняет данные на сервере в директории, указанной в конфигурационной директиве session.save_path.

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

Пример работы скрипта можно посмотреть по адресу https://beget.com/session_test.php.

Каким способом возможна блокировка сессий

На сайте php в секции описания работы сессий есть примечание (http://php.net/manual/ru/session.examples.basic.php):

Читайте также:  Android app java source code

Сессии, использующие файлы (по умолчанию в PHP), блокируют файл сессии сразу при открытии сессии функцией session_start() или косвенно при указании session.auto_start. После блокировки, ни один другой скрипт не может получить доступ к этому же файлу сессии, пока он не будет закрыт или при завершении скрипта или при вызове функции session_write_close().

Скорее всего это станет проблемой для сайтов, которые активно используют AJAX и делают несколько одновременных запросов. Простейшим путем решить эту проблему будет вызов функции session_write_close() сразу же как только все требуемые изменения в сессии будут сделаны, предпочтительно ближе к началу работы скрипта. Также можно использовать другой механизм сессии, который поддерживает конкурентный доступ.

В последнее время проблема блокирования сессий становится всё более частой. Отчасти это связано с усложнением сайтов и необходимостью производить больше вычислений на строне сервера, а так же с большим распространением AJAX. К сожалению, не всегда логика приложения, особенно если она сложная, позволяет эффективно ограничить время блокировки конкурирующих за сессию процессов. Ситуация усугубляется еще тем, что 3-5 подобных клиентов способны быстро забить зависшими и простаивающими в ожидании процессами PHP-воркеры, в результате чего сайт начнёт выдавать 5XX ошибку.

Самый простой пример блокировки сессий:

Если открыть этот файл сначала в первой вкладке, а потом во второй — вторая вкладка будет ждать, пока не доработает первая. То есть фактически вторая вкладка будет дожидаться, пока первая не освободит файл сессии (что занимает в конкретном случае 30 секунд). Данная проблема хорошо описана в блоге компании 1С-Битрикс на Habrahabr.

Какие варианты решения данной проблемы существуют

Для хранения сессий можно использовать БД, такие как MySQL или PostgreSQL (что не совсем правильно, учитывая возможности большинства БД и возможную скорость работы в данной задаче), Memcached (не гарантирует хранение сессии, возможно ее удаление) и Redis, который мы считаем оптимальным хранилищем. По скорости он не уступает Memcached, но при этом может гарантировать сохранность данных.

И самое главное приемущество Redis — при хранении в нем сессий они не блокируются.

В рамках нашей панели управления (cp.beget.com) можно включить хранение сессий в Redis для всех сайтов на аккаунте. Для этого необходимо перейти в раздел «Сайты», и далее отметить галочку — «Хранить сессии всех сайтов в Redis».

Дополнительные материалы

Источник

Обнаружена блокировка сессий в PHP

Здравствуйте! В течение последних десяти суток ваши сайты не отвечали 13 секунд из-за блокировки сессий в PHP. Используйте хранение сессий в Redis — это позволит избежать подвисания сайтов по этой причине. Использовать Redis ? В панели хостинга уведомление , сайт только перенесен к ним , посещаемости пока еще нет Что за? Спасибо

NVMe VDS (https://well-web.net/nvme-vps) с поддержкой 24/7 — от 545 руб.! Безлимитный хостинг (https://well-web.net/ssd-hosting) — от 129 руб.! Домен в подарок! Перенос бесплатно! Заказывайте сейчас, и получите скидку 50%! Заходи! (https://well-web.net/limited-offers)

Читайте также:  Html формула в таблице

Проверенные KVM NVMe VPS ( https://hosthatch.com/a?id=200 ) в Нидерландах, Швеции, Норвегии, Австрии и США с гарантированным ресурсом CPU — от $2,5/м за 1GB RAM, 10GB NVMe SSD Пожалуй, лучший веб-хостинг в России ( https://beget.com/p415216 ) (30 дней на тест)

Хостинг по цене героина. Достался по наследству интернет-магазин с посещаемостью 700-800, это сообщение у меня висело всегда, пока не свалил от туда. Там еще есть куча всяких ограничений.

ibatanov:
Хостинг по цене героина. Достался по наследству интернет-магазин с посещаемостью 700-800, это сообщение у меня висело всегда, пока не свалил от туда. Там еще есть куча всяких ограничений.

В отличии от Бигет, другие хостеры просто об этом молчат. То есть это не означает что на них ваш магазин как-то лучше работает. Но вы конечно можете так думать и спать спокойнее))

Обычная практика при использование Cloudlinux. Выбирать между 13 секундами за «10-ки» суток или использовать другие где нет жестоких ограничениях и при высокой нагрузке ложатся «все клиенты» решать ТС, но я б посмотрел варианты в сторону ВПС.

Источник

Отключаем от admin-ajax.php — снижаем блокировки сессий в PHP на сервере

dmin-ajax.php

В мне часто задают вопросы, связанные с работой скрипта admin-ajax.php на хостинге (часто его работа прерывается, заканчивается ошибкой или вызывает нагрузку на хостинг). Как решить все проблемы?

Что такое admin-ajax.php

Скрипт admin-ajax.php (так называемый WordPress heatbeat, включен с версии WordPress 3.5.2) выполняет продление пользовательской сессии WordPress — для удобства использования административной панели. Если администратор или редактор часто работает с сайтом, то это избавляет от необходимости каждый раз вводить логин/пароль. Но для 99% посетителей сайта этот функционал, скорее всего, не нужен: они ведь только читает контент, не редактируют его.

В ряде случаев admin-ajax.php может отвечать за повышенное потребление памяти и CPU на хостинге: за счет частых — каждые 15 секунд — обращений к базе данных на фоне других запросов (большинство из которых уже могут быть закэшированы). Поскольку функционал admin-ajax.php является динамическим (его нельзя кэшировать), то облако Айри, как и любой другой кэширующий инструмент, пропускает все запросы напрямую к серверу, создавая существенную нагрузку.

dmin-ajax.php

Как бороться с admin-ajax.php

Лучшим способом устранение нагрузки от admin-ajax.php является полное отключение этого функционала. Лучше всего это осуществить либо редактированием внутри движка WordPress, либо путем установки соответствующего плагина.

Для отключения WordPress Heartbeat для всех страниц, кроме страницы создания новой записи, нужно добавить в header.php или function.php вашей темы:

add_action( ‘init’, ‘my_deregister_heartbeat’, 1 ); function my_deregister_heartbeat()

Для решения этой проблемы через плагины WordPress можно использовать AJAX Heartbeat Tool или Heartbeat Control.

Источник

Оцените статью