tgoop.com/javaproglib/6663
Create:
Last Update:
Last Update:
Один из подписчиков поделился кейсом, который едва не превратился в катастрофу — и всё из-за, казалось бы, безобидного таймера.
История от подписчика:
В микросервисе на Spring Boot был реализован механизм повторных попыток через ScheduledExecutorService. Всё шло нормально — до запуска в проде.
Через пару дней после релиза начали сыпаться алерты: увеличилось потребление памяти, а сервис стал отвечать с задержками. Логи молчали, метрики CPU были в порядке, но heap распухал как на дрожжах.
После анализа heap dump выяснилось: каждый раз при неудачной операции создавался новый ScheduledFuture, который не отменялся и оставался висеть в памяти. Таймеры копились, ссылки не освобождались, GC с ума сходил.
Ввели пул повторных задач с ограничением количества активных таймеров и явной отменой по завершении. Также поставили алерты на рост количества активных future’ов. Память стабилизировалась, сервис вернулся к нормальной работе.