2012-02-20 2 views
9

Наше приложение php, работающее под apache, иногда пытается заблокировать удаленный файл сеанса, это зависает с процессом apache, и в итоге у нас заканчиваются процессы.php блокирует удаленный файл сеанса

Доказательства:

strace : flock(89, LOCK_EX     -----stuck in flock for File Descriptor 89 

, а затем:

Lsof, для того же процесса:

httpd 22161 apache 89u ... /var/lib/php/session/sess_mf7svvirg7rbu9l0m5999pm6h4 (deleted) 

Любые идеи, почему это происходит? И что мы можем сделать, чтобы предотвратить это?

+2

а) Этот вопрос, вероятно, лучше направлен http://webmasters.stackexchange.com/ б) Кто удалил файл сеанса? Вы или PHP? Как давно он был удален? Вы уверены, что он был удален и не просто заблокирован другим процессом? – DaveRandom

+1

Вы используете управление сеансом php или пользовательский обработчик сеанса? – dqhendricks

+0

Что-нибудь приходит через журнал ошибок, который может связать, почему это происходит? –

ответ

0

Не знаю, почему для вашего случая.

Этот question получили некоторые хорошие предложения ...

Вы пробовали переустановить окружающую среду, или переход на другой сервер? Будет ли он работать, если вы переустановите обработчик сеанса по умолчанию и используете fopen ($ file, 'w') вместо fopen ($ file, 'x')?

Кроме того, обходной путь реализации обработчика сеанса на основе базы данных, например, для установки «обработчика сеансов php и mysql» существует миллион или около того.

1

Есть ли какой-нибудь огромный (клиентский) файл сеанса? Вы не должны этого делать. Сам PHP реализует механизм сбора мусора для удаления несуществующих файлов сеанса. Это будет much more efficient, чем все, что вы могли бы написать с помощью PHP.

Вы можете использовать:

  1. session_destroy - Уничтожает все данные, зарегистрированные в сессии
  2. session_unset - бесплатные все переменные сессии

И делать session_start() снова.

Подробнее here.

Update:

PHP очень чистый скриптовый движок, который не оставляет мусор в вашей системе! Файлы сеанса автоматически удаляются после достижения таймаута сеанса. session-timeout может быть случай с вашей системой, я так думаю. Поэтому, если тайм-аут установлен на 20 минут, файлы будут удалены через 20 минут после последнего доступа. То же самое для печенья. Каждый раз, когда запрашивается страница, cookie-ttl устанавливается на + 20 минут.

Проверьте некоторые из configuration directives. Скорее всего, вы установили gc_maxlifetime в очень высокое значение, и они просто не достигли предела «истечения», который будет автоматически собран. Вы должны проверить свои приложения, чтобы убедиться, что они не задают странные значения для параметров сеанса (используя ini_set()) во время выполнения.

PHP имеет внутренний алгоритм, который работает на session_start(), который решает, должен ли он выполнять очистку мусора и удалять старые файлы сеанса.По соображениям производительности, я полагаю, что шанс по умолчанию выполнить прогон каждый раз составляет 1%, поэтому в среднем процедура сбора мусора будет запускаться один раз в каждые 100 вызовов session_start(). Если вы обнаружите, что этого недостаточно, вы можете повысить настройку gc_divisor до значения, превышающего 1.

+0

Я не думаю, что он делает это намеренно ... вопрос в том, почему PHP пытается удалить файл сеанса. –

+0

Я прочитал 'is occaisionally пытается заблокировать удаленный файл сеанса'. Так вот, я дал этот ответ. Тогда основная проблема заключается в том, какой код пытается удалить файл сеанса. –

+0

Если ОП уже знал, что именно пытается заблокировать удаленный файл сеанса, тогда не было бы никаких сомнений. –

0

Это, вероятно, что-то более обходное решение для вашего случая, но почему бы вам не перенести сеансы вообще из файловой системы в базу данных?

Вы можете получить более подробную информацию здесь http://php.net/manual/en/function.session-set-save-handler.php

0

ли вы пробовали читать эти 2 открытых ошибок?

https://bugs.php.net/bug.php?id=47640 https://bugs.php.net/bug.php?id=32092

Try называть session_write_close() (некрасиво обходного) в качестве последней строки или обновить PHP.

3

У меня возникла проблема с идентичными симптомами, за исключением того, был ли файл сеанса удалён или нет, не имеет значения (и может быть для вас тоже - есть ли у вас доказательства того, что удаление файла сеанса связано с flock ?).

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

  1. /page1.php выполняет хорошо, когда загружен. Он включает javascript, который выполняет XMLHttpRequest до /background.php.
  2. При обращении к /background.php он запускает readfile(http://remote.url), что является несуществующим URL-адресом.
  3. При переходе на /page2.php сценарий застопорился. Строка показывает flock(89, LOCK_EX, а lsof указывает, что она ожидает доступа для чтения/записи в файле сеанса.

В этом случае, как и /page2.php/background.php оба ждут на той же сессии файл, но тот не смог сделать это, потому что была задержана в ожидании readfile() отключалось. Я получил это в php_error_log:

PHP Warning: readfile(http://remote.url): failed to open stream: Connection timed out in […]/background.php on line […] 

Таким образом, проблема была с совершенно иным сценарием, чем воспринимаемый виновник.

Вы можете проверить эту проблему быстро оглавлению все открытые файлы для файла PHP сессии, чтобы увидеть, который HTTPD процесс использует его:

$ sudo lsof | grep sess_it9q6kkvf83gcj72vu05p9fcad7 
httpd  31325 apache 74u  REG    8,5  410 11634061 /var/lib/php/session/sess_it9q6kkvf83gcj72vu05pfa543 
httpd  31632 apache 74uW  REG    8,5  410 11634061 /var/lib/php/session/sess_it9q6kkvf83gcj72vu05pfa543 

Если два HTTPD процессы имеют доступ к одному файлу сеанса, вероятно, это это ваша проблема. Теперь вы можете проверить, что эти процессы делают трассирование, или в моем случае это было достаточно, чтобы использовать apachectl fullstatus:

$ sudo apachectl fullstatus | grep 31632 
5-7 31632 0/1/1169 _ 0.05 6  30692 0.0 0.02 3.45 111.222.333.444 www.example.com.com  /background.php 
Смежные вопросы