предупреждения php session_write_close

предупреждения php session_write_close

Все наши ошибки регистрируются в NewRelic, и мы всегда видели несколько предупреждений session_write_closeв журнале ошибок. Однако частота ошибок увеличилась и теперь они заполняют наш 24-часовой журнал.

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

Вот полное сообщение об ошибке:

Error message
E_WARNING: session_write_close(): Failed to write session data (files).    
Please verify that the current setting of session.save_path is correct        
(/opt/php55/var/lib/php/session-nginx)

Поэтому я проверил, сколько файлов находится в этом каталоге 9431и какие у них права -rw------- 1 nginx nginx.

Я не вижу ничего неправильного в моей конфигурации, правах файлов и т. д.

У нас нет вариантов. Что я могу сделать, чтобы решить эту проблему? В настоящее время затрагивает < 1% наших пользователей, мы просто хотим сохранить нашу ставку как можно ниже.

Вот список моей конфигурации php.ini.

Directive   Local Value Master Value
session.auto_start  Off Off
session.cache_expire    180 180
session.cache_limiter   nocache nocache
session.cookie_domain   no value    no value
session.cookie_httponly Off Off
session.cookie_lifetime 0   0
session.cookie_path /   /
session.cookie_secure   Off Off
session.entropy_file    /dev/urandom    /dev/urandom
session.entropy_length  32  32
session.gc_divisor  1000    1000
session.gc_maxlifetime  1440    1440
session.gc_probability  1   1
session.hash_bits_per_character 5   5
session.hash_function   0   0
session.name    PHPSESSID   PHPSESSID
session.referer_check   no value    no value
session.save_handler    files   files
session.save_path   /opt/php55/var/lib/php/session-nginx    /opt/php55/var/lib/php/session-nginx
session.serialize_handler   php php
session.upload_progress.cleanup On  On
session.upload_progress.enabled On  On
session.upload_progress.freq    1%  1%
session.upload_progress.min_freq    1   1
session.upload_progress.name    PHP_SESSION_UPLOAD_PROGRESS PHP_SESSION_UPLOAD_PROGRESS
session.upload_progress.prefix  upload_progress_    upload_progress_
session.use_cookies On  On
session.use_only_cookies    On  On
session.use_strict_mode Off Off
session.use_trans_sid   0   0

Немного статистики сервера: CentOS 6.6 PHP 5.5.28 Nginx 1.6.2 Любая помощь приветствуется!

решение1

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

Я бы также не использовал сборку мусора сессии php, которая откладывает сборку мусора от заданий веб-запросов. Я бы создал собственную задачу для обработки этого, либо запуская ее из cron, либо из какой-то системы очередей заданий.

Есть ли у вас уже какая-либо система очистки сессий помимо сборки мусора сессий PHP?

Соответствует ли частота, с которой это происходит, 0,1% времени, что соответствует вашим session.gc_divisorнастройкам?

Ваши процессы php запущены как пользователь nginx? Это php, а не nginx, выполняет очистку на основе настроек session.gc_*. Если php запущен как nginx, это хорошо с точки зрения доступа к файлам сеанса php, но, вероятно, плохо с точки зрения совместного использования идентификатора пользователя с сервером nginx.

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

Я также обеспокоен, если вы не настраиваете session.save_pathчто-то конкретное для своего приложения. Это будет означать, что если у вас есть несколько приложений, совместно использующих один и тот же каталог сеансов, то при запуске сборки мусора побеждает приложение с самым коротким сроком действия, очищая сеансы другого приложения.

решение2

Очевидное наблюдение, которое я сделал из вашего вопроса, заключается в том, что у вас слишком много узких мест при попытке сохранить файлы в /opt/php55/var/lib/php/session-nginx. Поэтому ваше решение — устранить узкие места, сначала диагностировав, что конкретно идет не так.
Предполагая, что он гонится за записью на диск, и ошибки являются признаком того, что он сдается, я бы ожидал ошибок dmesg, показывающих проблемы с записью на диск. Если это так, вы можете записывать в память или использовать другие решения, которые представляют собой более быстрый «диск».
mc0e упоминает memcached вместо использования save_handle=files, это хороший вариант. Альтернативой memcached может быть использование tmpfs, который по сути помещает сессию в память точно так же (поэтому имеет быстрое время записи), но не требует нового приложения.
Я бы также задал вопрос, какая файловая система находится в /opt/php55/var/lib/php/session-nginx? Вам не нужно все сложное журналирование ext3/4 для того, что по сути является операцией типа mktmp. Вы можете создать папку в /tmp и сделать на нее символическую ссылку, чтобы снизить накладные расходы при создании файлов.
Какова конфигурация оборудования? Если это один диск без кэширования, вы должны увидеть проблемы в dmesg, если вы достигли предела его производительности. Я использовал контроллеры AMCC Raid с Raid-1 на всех своих серверах. Если это Raid-1 (зеркало), чтение будет быстрым, но скорость записи будет зависеть от того, насколько хорошо реализован рейд (я знаю, что AMCC может распределять записи по дискам в Raid-1, но не все реализации RAID-1 делают это, я знаю, что программный рейд этого не делает). Мой старый босс поклялся в Raid-5 по этой причине, и пока это настоящий аппаратный рейд (RAID-5 может быть дорогим для ЦП, если это не так), это радикально ускорит пропускную способность вашего диска. Другой вариант — твердотельный накопитель, но если вы действительно идете по этому пути, я бы рекомендовал использовать memcached или tmpfs, поскольку больший объем памяти всегда является хорошим планом (по сравнению с любым другим новым оборудованием).

Однако самым простым решением будет создание /tmp/session-nginx и символической ссылки или монтирование /opt/php55/var/lib/php/session-nginx в /tmp/session-nginx/.

решение3

Часть вопроса касается сложности отслеживания таких ошибок, поэтому я могу предложить явно закрыть сессию в вашем коде в блоке try/catch. Обработайте исключение, усните и попробуйте снова.

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

Есть несколько конфигураций, которые я бы подправил, чтобы посмотреть, что получится:

  1. увеличить лимит открытых файлову вас может быть установлен какой-то нижний предел для какой-то части вашей ОС. Например, мой ноутбук поддерживает сотни тысяч открытых файлов, но только 4000 от одного пользователя.

  2. уменьшите maxrequestperchilds до 1000это заставит каждый http-сервер перезапуститься после обслуживания 1000 клиентов.

  3. уменьшить MaxClientsиувеличить ListenBacklog. Это очень, очень нелогично, но если вы установите MaxClients/Servers слишком высоко, множество процессов будут бороться за ресурсы на вашем сервере и вызывать узкие места. Это сильно зависит от типов узких мест, которые у вас есть. У меня это серверы баз данных.

Связанный контент