Все наши ошибки регистрируются в 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. Обработайте исключение, усните и попробуйте снова.
Другая часть вопроса описывает ошибку записи, которая, кажется, носит случайный характер. Это не то, чего я ожидаю от неправильных разрешений. Я подозреваю, что у вас слишком много открытых файлов.
Есть несколько конфигураций, которые я бы подправил, чтобы посмотреть, что получится:
увеличить лимит открытых файлову вас может быть установлен какой-то нижний предел для какой-то части вашей ОС. Например, мой ноутбук поддерживает сотни тысяч открытых файлов, но только 4000 от одного пользователя.
уменьшите maxrequestperchilds до 1000это заставит каждый http-сервер перезапуститься после обслуживания 1000 клиентов.
уменьшить MaxClientsиувеличить ListenBacklog. Это очень, очень нелогично, но если вы установите MaxClients/Servers слишком высоко, множество процессов будут бороться за ресурсы на вашем сервере и вызывать узкие места. Это сильно зависит от типов узких мест, которые у вас есть. У меня это серверы баз данных.