Все наши ошибки регистрируются в 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 Любая помощь приветствуется!
С сильно загруженным сервером я бы использовал memcached
(может быть даже redis
?) для хранения сеанса. Так что, если бы я был в вашей ситуации, я бы, вероятно, просто настроил это ради себя, а затем посмотрел, исчезла ли проблема просто случайно.
Я также не стал бы использовать сборку мусора сеанса php, которая вешает сборку мусора на задания веб-запросов. Я бы настроил свое собственное задание, чтобы справиться с этим, либо из cron, либо из какой-либо системы очереди заданий.
У вас уже есть какая-либо система очистки сеанса за пределами сборки мусора сеанса php?
Скорость, с которой это происходит в 0,1% случаев, соответствует вашему session.gc_divisor
установка?
Ваши процессы php работают от имени пользователя nginx? Это php, а не nginx, который выполняет очистку на основе session.gc_*
настройки. Если php работает как nginx, это хорошо с точки зрения доступа к файлам сеанса php, но, вероятно, плохо с точки зрения совместного использования идентификатора пользователя с сервером nginx.
Вам может потребоваться разрешение на выполнение в этом каталоге сеанса, чтобы ваша сборка мусора могла видеть, что нужно очистить.
Я также был бы обеспокоен, если вы не устанавливаете session.save_path
к чему-то конкретному для вашего приложения. Это будет означать, что если у вас есть несколько приложений, совместно использующих один и тот же каталог сеанса, то при запуске сборки мусора побеждает приложение с самым коротким сроком действия, очищая сеансы другого приложения.
Очевидное наблюдение, которое я сделал из вашего вопроса, заключается в том, что у вас слишком много узких мест при попытке сохранить файлы в / 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 /
Частично вопрос заключается в том, что такого рода ошибки сложно отслеживать, поэтому я могу предложить явно закрыть сеанс в вашем коде в блоке try / catch. Обработайте исключение, спите и попробуйте еще раз.
Другая часть вопроса описывает ошибку записи, которая кажется случайной по своей природе. Это не то, чего я ожидаю от неправильных разрешений. Я подозреваю, что у вас слишком много открытых файлов.
Есть несколько конфигураций, которые я бы настроил, чтобы увидеть, что произойдет:
увеличить лимит открытых файлов у вас может быть установлен какой-то нижний предел для какой-то части вашей ОС. Например, мой ноутбук поддерживает сотни тысяч открытых файлов, но только 4000 от одного и того же пользователя.
уменьшите maxrequestperchilds до 1000 это заставит перезапустить каждый http-сервер после обслуживания 1000 клиентов.
уменьшить MaxClients и увеличить ListenBacklog. Это очень, очень нелогично, но если вы установите слишком большое значение MaxClients / Servers, многие процессы будут бороться за ресурсы на вашем сервере и вызывать узкие места. Это сильно зависит от того, какие у вас узкие места. Моя - это серверы баз данных.