Почему мы перестали будить инженеров по ночам, или как устроен честный автоперезапуск сервисов
3:42 ночи. Август прошлого года. Телефон на тумбочке вибрирует с такой яростью, будто начался апокалипсис. На экране двадцать непрочитанных пушей из рабочего чата: бот для приема заказов крупной доставки лег, клиенты не могут оплатить корзину, поддержка в панике тегает разработку.
Я открываю ноутбук заспанными глазами, вбиваю пароль от VPN, подключаюсь по SSH к серверу и пишу команду, которую знаю наизусть: docker restart bot_core. Бот оживает за три секунды. Проблема решена. Клиенты платят. Я закрываю крышку ноута, ложусь обратно, но уснуть уже не могу — в крови гуляет адреналин, а в голове вертится один и тот же злой вопрос: зачем здесь вообще был нужен я?
Человек не должен работать дорогостоящим костылем между системным сбоем и кнопкой «перезагрузить». Если вся ваша ночная дежурная смена сводится к тому, чтобы проснуться, пнуть упавший процесс и упасть лицом в подушку, вы занимаетесь ерундой. Мы в GuardLabs поняли это после десятков подобных инцидентов, когда поняли простую истину: мониторинг, который только кричит о беде, бесполезен.
Иллюзия «restart: always»
Первое, что делает любой джун, когда у него падает скрипт — прописывает в docker-compose restart: always или настраивает базовый перезапуск в systemd. Кажется, что победа близка. На практике вы просто меняете одну проблему на другую, куда более опасную.
Что происходит, если у вас упала база данных или внешний платежный шлюз отвечает пятисотками? Бот падает на старте. Docker тут же запускает его снова. Бот снова падает. Через две минуты процесс уходит в бешеный цикл перезапуска (crash loop), спамит сторонний API сотнями авторизационных запросов и ловит перманентный бан по IP за подозрительную активность. Мы видели, как Telegram отправлял ботов в жесткий rate limit на 24 часа просто потому, что скрипт настойчиво долбился в API каждые 300 миллисекунд после падения.
Вторая беда — зомби-процессы. Процесс формально жив, PID существует, память потребляется, но Event Loop намертво заблокирован зависшим синхронным вызовом. Стандартный супервизор операционной системы видит, что процесс крутится, и радостно рапортует: «Все отлично». А клиенты тем временем жмут на кнопки в интерфейсе и видят бесконечную пустоту.
Как работает настоящий watchdog для ботов
Когда мы начали строить свой собственный watchdog для ботов и фоновых сервисов, мы сразу выкинули на помойку наивные проверки через ps aux. Чтобы автоматика действительно снимала головную боль, она должна действовать как въедливый тестировщик.
Схема, к которой мы пришли через шишки и ночные алерты, состоит из трех жестких звеньев. Первое — внешняя проверка жизнеспособности (liveness probe). Наш наблюдатель отправляет сервису реальный запрос раз в 30 секунд. Для бота это может быть скрытый эндпоинт, проверка очереди задач в Redis или ответ на тестовую команду через локальный сокет. Если ответа нет дольше заданного таймаута — сервис признается недееспособным.
Второе звено — контролируемое автовосстановление после сбоя. Мы не перезапускаем всё подряд вслепую. Сначала сторожевой процесс берет паузу, сбрасывает зависшие сетевые соединения, проверяет, доступны ли зависимости (например, та же база данных), и только потом выполняет мягкий рестарт с экспоненциальной задержкой. Если сервис упал один раз из-за редкой утечки памяти — рестарт решит задачу мгновенно.
Но самое главное — третье звено. Контроль результата. После перезапуска наблюдатель обязан дождаться успешного ответа от сервиса. Если процесс поднялся, прошел внутренние тесты и начал стабильно отвечать — инцидент закрывается.
Принцип гробовой тишины
Знаете, какая самая частая ошибка при настройке оповещений? Спамить разработчиков каждым успешным действием. Если вам в рабочий чат падает двадцать сообщений в день в духе «Сервис упал, но я его перезапустил, спите спокойно», через неделю вы перестанете читать этот чат. Это классическая усталость от алертов (alert fatigue).
Мы исповедуем совершенно другой подход: эскалация только при неразрешённой проблеме. Если система справилась сама — запиши факт в лог, сохрани дамп памяти на диск для утреннего разбора и молчи. Не трогай живых людей. Пусть разработчики спят, а утром за чашкой кофе спокойно посмотрят, почему в 4 утра произошел единичный сегфолт.
Но если автоматический перезапуск провалился раз, второй, третий — вот тогда пора включать сирену. Это значит, что сломалось что-то фундаментальное: кончилось место на диске, отвалился DNS-провайдер или кто-то выкатил кривую миграцию схемы БД. В таких случаях автоматика бессильна, и человек нужен немедленно. Но когда инженер просыпается от такого алерта, он точно знает: это не ложная тревога и не пустяк. Случилось то, что требует его мозгов, а не просто пальца на клавише Enter.
Считайте стоимость своего сна
Полноценный мониторинг сервисов с автоперезапуском — это не роскошь для enterprise-инфраструктур с миллионными бюджетами. Это базовая гигиена для любого продакшена, будь то парсер, микросервис обработки платежей или клиентский телеграм-бот, приносящий вам деньги.
Каждый сбой, требующий ручного вмешательства человека ночью, обходится слишком дорого. Вы теряете конверсии, пока дежурный протирает глаза и ищет зарядку от ноутбука. Вы получаете выгоревшую команду, которая ненавидит свой продукт, потому что он дергает их на выходных. Наконец, вы рискуете человеческим фактором: заспанный сисадмин в консоли продакшена в четыре утра — это идеальный рецепт для случайного rm -rf не в той директории.
Если вам надоело быть нянькой для собственных серверов и просыпаться от каждого падения процессов, посмотрите на наше решение — Watchdog-бот: автовосстановление упавших сервисов. Мы берем на себя круглосуточное наблюдение за вашими ботами и микросервисами, поднимаем их в ту же секунду, когда они споткнулись, и дергаем вас только тогда, когда без прямого вмешательства разработчика действительно не обойтись. Спите спокойно, пока код работает.