Глава 31 / 51
Том 4 · Глубокое погружение в перезагрузку (финал)

Границы и антипаттерны: горячая перезагрузка — не универсальный молоток

Знать «когда не надо» не менее важно, чем «как». Финал тома 4: все границы сводятся в одну таблицу, а реальный атакующий образец проверяет устойчивость системы.

Обзор

Позиционирование: «негативный список» тома 4. Антипаттерны — из реальных сцен: атакующие образцы drill, штормовые кейсы func_test и частое искушение принять перезагрузку за инструмент развёртывания.

31.1 Введение

Горячая перезагрузка решает онлайн-обновление бизнес-кода. Она не решает: изменение структуры процесса (эндпоинты/потоковая модель), пересоздание не-скриптовых ресурсов — и не годится для высокочастотных релизов. Предикат прост: если изменение касается только «содержимого скриптов + сертификатов + конфигурации на тех же эндпоинтах» — reload; остальное — рестарт. Высечь эту границу в эксплуатационном мануале полезнее, чем помнить десять деталей.

31.2 Сводка неизменяемого

ИзменениеИсход reloadВерный путь
engine.workersFAILED (отклонено)рестарт процесса
неизменяемые поля слушателя (recv_limit и др.)FAILED (явный отказ)рестарт процесса
структура эндпоинтов (комбинации class/ip/port без handoff)FAILED (с подсказкой деградации)рестарт; или два server с прокаткой
скрипты сервисов класса customонлайн-перезагрузка не поддерживаетсярестарт (у «сырых» ресурсов нет терминального lease)
добавление / удаление custom serverне поддерживаетсярестарт
содержимое скриптов / сертификаты / конфигурация тех же эндпоинтовSUCCEEDEDreload (это ровно его работа)

Обратите внимание на место custom: он отдаёт соединения и ресурсы целиком приложению, и хост не получает сигнала «когда безопасно» — потому честно говорит «не поддерживается», а не даёт небезопасный тумблер. Бизнес, которому нужны горячие обновления, живёт на четырёх классах http/ws/tcp/udp.

31.3 Перезагрузочные бомбы и устойчивость

В списке атакующих образцов drill есть пункт прямо по горячей перезагрузке: перезагрузочная бомба из битых скриптов — циклическая подача нескомпилируемых скриптов (образец — 6 подряд), вместе со штормовым кейсом func_test на 20 выстрелов, проверяет три точки устойчивости:

перезагрузочная бомба (битые скрипты ×N очередью) ├── каждое намерение: FAILED + Message с ошибкой компиляции /* отказ чистый */ ├── старое поколение всё время обслуживает как ни в чём не бывало /* отказ не ранит онлайн */ └── latest-wins поглощает конкурентный шторм /* очереди не копятся */ сопровождающие защиты: pending ≤64 (при переполнении Submit возвращает 0) кольцо результатов 256 (аудит не растёт бесконечно) хороший скрипт сразу за битыми → одно SUCCEEDED и сервис восстановлен

Смысл существования образца: поверхность перезагрузки — атакующая поверхность; аутентификация управляющих маршрутов (гл. 27) отсекает внешний запуск, а сам механизм гарантирует: даже промах своего человека приносит лишь чистый отказ за плохой ввод.

31.4 Собрание антипаттернов

АнтипаттернСимптомВерное решение
reload каждую секунду (как система развёртывания)копятся издержки компиляции; очередь GC растётперезагрузка — изменение, не релиз; высокочастотная итерация — через рестарт в dev
В Swap запихнули целую базусмена замедляется; снимок распухаетбольшие данные — в db/файлы (межпоколенческие от природы); Swap несёт лишь лёгкое состояние
Совместное использование голых указателей между поколениями «для удобства»случайные UAFпередача значений (Swap) или глобальные синглтоны-ресурсы с явным временем жизни
reload как лекарство от «странного состояния памяти»заглушение симптома; проблема возвращаетсячинить причину; перезагрузка — не мистическая кнопка сброса (хотя часто «помогает»)
Автозапуск по файлам в продакшнеавтосохранение редактора = случайный релизавтозапуск — только dev; продакшн через управляющие маршруты с аутентификацией

31.5 Контракт

  • Граница: скрипты/сертификаты/конфигурация тех же эндпоинтов → reload; структура/потоки/custom → рестарт.
  • Устойчивость: плохой ввод = чистый отказ + целое старое поколение + ограниченные очереди.
  • Дисциплина: частота перезагрузок и объём Swap остаются «человеческими» (изменения минутного уровня, снимки килобайтного).

Частые ошибки

Порт хотят поменять через reload
Симптом
FAILED; Message указывает на структурное изменение.
Причина
Смена эндпоинта требует пересборки слушателя — безопасная онлайн-замена слушателя идёт через переходный новый порт (прокатка двух server) или рестарт. Это не дефект, а честная граница.
Поиск reload для custom-сервиса
Симптом
Документы/интуиция говорят «перезагружается», а пути нет.
Причина
У класса custom соединения и ресурсы целиком у приложения — хост не может определить безопасную точку. Горячий бизнес — на четыре классах протоколов; custom оставьте действительно особым сценам.

Упражнения

БазовыйЧек-лист границ

По очереди вызовите изменения таблицы 31.2 и зафиксируйте каждое сообщение reload.

Приёмка: все шесть строк подтверждены; у каждого отказа явный Message.
ПродвинутыйВоспроизведение бомбы

Повторите перезагрузочную бомбу: 20 битых скриптов очередью + один хороший в середине, всё под нагрузкой.

Приёмка: 20 FAILED + 1 SUCCEEDED; ноль отказов нагрузки; хороший скрипт вступает в силу немедленно.
ВызовПрокатка смены порта

Спроектируйте и реализуйте «смену порта без простоя» (подсказка: временные два server + переключение клиента + уборка).

Приёмка: доступность 100% на всём пути; для каждого шага прописан путь отката.

Итоги

ТезисВывод
Предикатскрипты/сертификаты/конфигурация тех же эндпоинтов → reload; остальное рестарт
Неизменяемоеworkers, поля слушателя, структура эндпоинтов, класс custom
Устойчивостьплохой ввод чисто отклоняется, старое поколение цело, очереди ограничены
Дисциплинаизменения минутного уровня, снимки килобайтного, в продакшне без автозапуска
Финал тома 4модель→запуск→передача→хронология→GC→границы: контур горячей перезагрузки замкнут
Что дальше по xrt