Кейс: /health отвечал UP, пока consumer не обработал ни одного сообщения за час
Под в проде считался healthy по readiness-пробе — actuator возвращал 200 и статус UP. Трафик продолжал идти, k8s не перезапускал под. Проблему нашли не через health check, а через метрику consumer lag: поток обработки Kafka внутри приложения упал с необработанным исключением в цикле poll и просто завершился.
Причина в том, что actuator агрегирует статус только из зарегистрированных HealthIndicator. Из коробки там были DiskSpace и DataSource — база была жива, диск был жив, поэтому агрегированный статус оставался UP. Никто не написал индикатор, который проверял бы, что consumer-поток вообще жив и последний poll был недавно.
Починили добавлением кастомного HealthIndicator: он хранит timestamp последнего успешного poll и сравнивает с текущим временем — если разрыв больше допустимого, статус переходит в DOWN.
Спросят, как правильно развести readiness и liveness для такого случая: liveness должен рестартовать под, если внутренний поток обработки умер, readiness — просто перестать слать трафик. Ещё уточнят, почему нельзя просто обложить consumer try/catch — потому что вопрос не в перехвате исключения, а в том, что снаружи об этом никто не узнаёт.
Health check честен ровно настолько, насколько его научили проверять то, что действительно важно для этого сервиса.
Тренажёр: 600 вопросов, мок с таймером, план повторов
senior·base — что спрашивают на самом деле
В этом посте были ссылки, но мы их удалили по правилам Сетки