Как понять, что джоба отваливается, если она висит восемь часов
Что проверяют
Отличаете ли вы долгую работу от зависания и умеете ли доказать это данными, а не ощущением. Вопрос поведенческий, поэтому ждут историю: что случилось, как нашли причину и что поменяли. Следом спрашивают, как сделать, чтобы о зависании узнавали не через восемь часов.
Как отвечать
Главная мысль: «висит» и «работает долго» различаются прогрессом. Если счётчик обработанных записей растёт, джоба жива. Если стоит, её надо разбирать.
- прогресс: в Spring Batch это
READ_COUNTиCOMMIT_COUNTвBATCH_STEP_EXECUTION, в своём коде метрика или heartbeat в лог раз в несколько минут; - дампы потоков:
jcmd <pid> Thread.printилиjstackдва-три раза с интервалом в полминуты. Один и тот же стек во всех дампах значит, что поток стоит. СостояниеBLOCKEDуказывает на монитор, а о найденном deadlock JVM пишет в конце дампа сама; - внешние вызовы: частая причина это сеть без таймаута. Сокет JDBC-драйвера PostgreSQL по умолчанию ждёт бесконечно,
HttpURLConnectionтоже, пока таймауты не заданы. В дампе поток висит на чтении из сокета; - база:
pg_stat_activityи блокировки, запрос мог встать в очередь за чужой транзакцией; - память:
jstat -gcutilи GC-логи через-Xlog:gc*. Если сборщик работает почти непрерывно, джоба формально жива, но прогресса нет.
Дальше расскажите, что поменяли: таймауты на все внешние вызовы, алерт на отсутствие прогресса за N минут и на превышение обычной длительности. Назовите свои цифры: сколько обычно шла джоба, где стояла, сколько заняла диагностика. Если такого случая не было, скажите об этом прямо и пройдите по тем же шагам как по плану действий.
Где спотыкаются
Предлагают просто перезапустить джобу. Без дампа потоков причина теряется, и через неделю всё повторяется.
Смотрят только логи. Зависший поток ничего не пишет, поэтому тишина в логе ничего не объясняет, объясняет стек.
Ставят алерт на общее время, например «дольше десяти часов». О проблеме узнают утром, хотя прогресс остановился на второй минуте.