Границы и антипаттерны: горячая перезагрузка — не универсальный молоток
Знать «когда не надо» не менее важно, чем «как». Финал тома 4: все границы сводятся в одну таблицу, а реальный атакующий образец проверяет устойчивость системы.
Обзор
31.1 Введение
Горячая перезагрузка решает онлайн-обновление бизнес-кода. Она не решает: изменение структуры процесса (эндпоинты/потоковая модель), пересоздание не-скриптовых ресурсов — и не годится для высокочастотных релизов. Предикат прост: если изменение касается только «содержимого скриптов + сертификатов + конфигурации на тех же эндпоинтах» — reload; остальное — рестарт. Высечь эту границу в эксплуатационном мануале полезнее, чем помнить десять деталей.
31.2 Сводка неизменяемого
| Изменение | Исход reload | Верный путь |
|---|---|---|
engine.workers | FAILED (отклонено) | рестарт процесса |
| неизменяемые поля слушателя (recv_limit и др.) | FAILED (явный отказ) | рестарт процесса |
| структура эндпоинтов (комбинации class/ip/port без handoff) | FAILED (с подсказкой деградации) | рестарт; или два server с прокаткой |
| скрипты сервисов класса custom | онлайн-перезагрузка не поддерживается | рестарт (у «сырых» ресурсов нет терминального lease) |
| добавление / удаление custom server | не поддерживается | рестарт |
| содержимое скриптов / сертификаты / конфигурация тех же эндпоинтов | SUCCEEDED | reload (это ровно его работа) |
Обратите внимание на место custom: он отдаёт соединения и ресурсы целиком приложению, и хост не получает сигнала «когда безопасно» — потому честно говорит «не поддерживается», а не даёт небезопасный тумблер. Бизнес, которому нужны горячие обновления, живёт на четырёх классах http/ws/tcp/udp.
31.3 Перезагрузочные бомбы и устойчивость
В списке атакующих образцов drill есть пункт прямо по горячей перезагрузке: перезагрузочная бомба из битых скриптов — циклическая подача нескомпилируемых скриптов (образец — 6 подряд), вместе со штормовым кейсом func_test на 20 выстрелов, проверяет три точки устойчивости:
Смысл существования образца: поверхность перезагрузки — атакующая поверхность; аутентификация управляющих маршрутов (гл. 27) отсекает внешний запуск, а сам механизм гарантирует: даже промах своего человека приносит лишь чистый отказ за плохой ввод.
31.4 Собрание антипаттернов
| Антипаттерн | Симптом | Верное решение |
|---|---|---|
| reload каждую секунду (как система развёртывания) | копятся издержки компиляции; очередь GC растёт | перезагрузка — изменение, не релиз; высокочастотная итерация — через рестарт в dev |
| В Swap запихнули целую базу | смена замедляется; снимок распухает | большие данные — в db/файлы (межпоколенческие от природы); Swap несёт лишь лёгкое состояние |
| Совместное использование голых указателей между поколениями «для удобства» | случайные UAF | передача значений (Swap) или глобальные синглтоны-ресурсы с явным временем жизни |
| reload как лекарство от «странного состояния памяти» | заглушение симптома; проблема возвращается | чинить причину; перезагрузка — не мистическая кнопка сброса (хотя часто «помогает») |
| Автозапуск по файлам в продакшне | автосохранение редактора = случайный релиз | автозапуск — только dev; продакшн через управляющие маршруты с аутентификацией |
31.5 Контракт
- Граница: скрипты/сертификаты/конфигурация тех же эндпоинтов → reload; структура/потоки/custom → рестарт.
- Устойчивость: плохой ввод = чистый отказ + целое старое поколение + ограниченные очереди.
- Дисциплина: частота перезагрузок и объём Swap остаются «человеческими» (изменения минутного уровня, снимки килобайтного).
Частые ошибки
- Симптом
- FAILED; Message указывает на структурное изменение.
- Причина
- Смена эндпоинта требует пересборки слушателя — безопасная онлайн-замена слушателя идёт через переходный новый порт (прокатка двух server) или рестарт. Это не дефект, а честная граница.
- Симптом
- Документы/интуиция говорят «перезагружается», а пути нет.
- Причина
- У класса custom соединения и ресурсы целиком у приложения — хост не может определить безопасную точку. Горячий бизнес — на четыре классах протоколов; custom оставьте действительно особым сценам.
Упражнения
По очереди вызовите изменения таблицы 31.2 и зафиксируйте каждое сообщение reload.
Повторите перезагрузочную бомбу: 20 битых скриптов очередью + один хороший в середине, всё под нагрузкой.
Спроектируйте и реализуйте «смену порта без простоя» (подсказка: временные два server + переключение клиента + уборка).
Итоги
| Тезис | Вывод |
|---|---|
| Предикат | скрипты/сертификаты/конфигурация тех же эндпоинтов → reload; остальное рестарт |
| Неизменяемое | workers, поля слушателя, структура эндпоинтов, класс custom |
| Устойчивость | плохой ввод чисто отклоняется, старое поколение цело, очереди ограничены |
| Дисциплина | изменения минутного уровня, снимки килобайтного, в продакшне без автозапуска |
| Финал тома 4 | модель→запуск→передача→хронология→GC→границы: контур горячей перезагрузки замкнут |
- учебник xrt · HTTP-сервер — устойчивость сервера глазами библиотеки (тайм-ауты и защита от атак)