Задать вопрос

Зависает php процесс?

Предусловия: Laravel 5.2, php 7.0 либо php 7.1 (проверял на двух версиях).

Суть: есть воркер, берет задачи из Redis, обрабатывает. Когда выполнит N задач, помирает (есть неведомые утечки памяти, которые очень сложно отследить. Вариант с авторестартом воркеров через supervisor отлично работает и производительность не проседает).

Таких воркеров несколько тысяч и 99% из них работают корректно (несколько серверов, на каждом по 1000-1500 процессов).
После 5-40 минут работы воркер помирает, т.к. обработал N задач. Длительность работы каждого отдельного процесса не детерминированна, т.к. 1-я задача может занять 10 секунд, 2-я - полторы минуты, ..., N-я - 15 секунд.

Но с течением времени появляются неумирающие процессы (за сутки на одном сервере из 1000 процессов таких "зависших" оказывается 5-10 штук).
Они выполняют задачи, но при этом на 90-100% грузят каждый свое ядро.

Важный(?) момент: strace -p pid_зависшего процесса зависает на выводе

strace -p 22679
strace: Process 22679 attached
strace: [ Process PID=22679 runs in x32 mode. ]

При этом если предугадать нужный процесс и подключить strace заранее, то он не виснет. Т.е. strace -p 22679 до зависания подключили, логи системных вызовов бегут. Подключаемся к нему еще раз, но уже после "зависания", strace дает вывод, указанный выше.

Как определил, что процесс занимается полезной работой.

netstat -tulpna | grep 22679

Взял порты, которые слушает процесс, и проверил tcpdump.

Видны запросы к mysql, общения с Redis и т.д. Есть части логов tcpdump, которые для нашего конкретного приложения позволяют определить старт/завершение задач, полученных из очереди (специфические запросы).

Далее приложен кусок strace того процесса, который завис, но к нему подключились до зависания и strace не остановился.

https://pastebin.com/KHBQ5vsM

Есть очень отдаленно похожий баг https://bugs.xdebug.org/view.php?id=731

P.S. Laravel в тегах, возможно, никак не влияет на проблему, но не исключена проблема где-то внутри фреймворка.
  • Вопрос задан
  • 2366 просмотров
Подписаться 5 Сложный 1 комментарий
Пригласить эксперта
Ответы на вопрос 3
@BorisKorobkov
Web developer
Воркер "не умирает после N задач", потому что последнюю N-ную задачу он еще и не выполнил. А почему не выполнил - надо разбираться с вашими исходниками сайта, а не самого PHP. Где-то циклится.
Для начала обновите Laravel до последней версии (5.7.2).
Можно выставить set_time_limit, но это решение не проблемы, а последствий.
Для поиска причины пишите unut-тесты, наймите тестировщика, включайте логирование при вызове каждой функции и пр.
Ответ написан
Stalker_RED
@Stalker_RED
Добавьте лог (можно в бд):
Таск #456456 взят в работу воркером #1234, время старта 1970-01-01 12:45:33, время завершения 1970-01-01 12:45:56

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

Также можно для каждого воркера записывать время старта и время останова. Тогда можно легко понять какие из них давненько висят, и до сих пор не завершились.
Ответ написан
alekciy
@alekciy
Вёбных дел мастер
>несколько серверов, на каждом по 1000-1500 процессов)
Вероятно на серверах минимум по 32Гб? Точно памяти в такие моменты достаточно и нет вытеснения в своп? А сервера железные или виртуалки?
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы