Жизненный цикл поколения: полная хронология момента перезагрузки
Что происходит, если горячую перезагрузку подать при 10 конкурентных запросах в полёте? Глава рисует весь путь от компиляции до погребения старого поколения — эталонный ответ на вызов из гл. 3.
Обзор
29.1 Введение
Тяжелейшая часть горячей перезагрузки не «сменить код», а момент смены: порт всё ещё слушает? Кому принадлежат запросы в полёте? Как два поколения сосуществуют и как расстаются? Ответы прячутся в двух механизмах — слот слушателя (источник стабильности порта) и lease (источник принадлежности запросов). Нанизать их на хронологию — и есть эта глава.
29.2 Сквозная хронология
- t3 — линия раздела: до неё всё может провалиться и отмениться; после — только вперёд (новые намерения встают в очередь)
- переключение t5 атомарно: соединение начинается либо от старого, либо от нового поколения — «полупоколения» не бывает
- Каждый запрос от начала до конца видит одно поколение — ключевое свойство двойных поколений и весь секрет «правишь код — соединения живут»
29.3 Слоты слушателя и handoff
Handoff делает возможным «старое и новое поколение на одном порту»: слушающий socket никогда не закрывается и не переоткрывается — извне сервис ни на миллисекунду не становится недоступным. TLS-эндпоинты так же, и выбор личности из ClientHello (SNI) привязан cookie-механизмом к тому же Accept — рукопожатия не раскалываются между поколениями.
29.4 Держатели lease
| Держатель | Получение | Возврат |
|---|---|---|
| HTTP-запрос | после Accept через текущее поколение слота | ответ завершён + тело вычитано (keep-alive держит до конца соединения или переатрибуции следующим запросом) |
| Соединение WS / TCP | соединение установлено | терминал соединения (Close/Abort) |
| Дейтаграмма UDP | по разу на дейтаграмму | возврат по завершении обработки |
| Таймер | привязан к своему поколению при создании | сработал или умер со сменой поколения |
| Перехваченное соединение | в момент перехвата | когда вы наконец Close (контракт гл. 25) |
Поэтому ответ на «когда умирает старое поколение» целиком определяют lease: HTTP после смены обнуляется за секунды (вместе с тайм-аутами простоя keep-alive); сервисы с длинными соединениями могут тянуть долго — ровно тот механизм, за которым lifecycle-тест утверждает «старые keep-alive соединения остаются на старом скрипте, терминальная утилизация без тайм-аута».
29.5 Контракт
- Принадлежность: каждый запрос видит одно поколение; смена атомарна, порт не мерцает.
- Параллельность: за время сосуществования поколения не мешают друг другу; старое не принимает новых запросов.
- Утилизация: время смерти старого поколения = возврат последнего lease (детали GC — гл. 30).
Частые ошибки
- Симптом
- Ожидания вроде «трафик поровну между старым и новым» после перезагрузки разбиваются.
- Причина
- После переключения указателя слота все новые соединения идут в новое поколение — старое только выпускает. Нужен канареечный розлив — берите vhost / два server, а не пропорции поколений.
- Симптом
- После подачи в логе нет нового номера gen — решено, что не подействовало.
- Причина
- Номер gen живёт в строке
script loaded; если отпечаток содержимого тот же (Revision совпал) или цель написана неверно (сверьте поле result.Target), смены поколения вовсе не было. Ориентируйтесь на терминал xsReloadQuery, а не на догадки по логу.
Упражнения
Не подглядывая, нарисуйте хронологию 29.2 с отметками t3 (необратимая точка) и t5 (переключение указателя).
Длинным соединением (WS) + тремя быстрыми перезагрузками соберите три доказательства, что соединение от начала до конца обслуживает одно поколение (поведенческий маркер, gen в логе, данные Swap).
По образцу reload_matrix: поток-молот долбит /ready каждые 10 мс, вы тем временем меняете поколение 5 раз; посчитайте отказы.
Итоги
| Тезис | Вывод |
|---|---|
| Скелет хронологии | снимок→компиляция→Swap→необратимая точка→Init→переключение указателя→lease в ноль→GC |
| Стабильность порта | слоты держат socket и переключают pData — handoff без мерцаний |
| Двойные поколения | старое только выпускает; каждый запрос видит одно поколение |
| Таблица lease | у запросов/соединений/дейтаграмм/таймеров/перехватов свои точки взятия и возврата |
- справочник xrt · atomic — порядок памяти за переключением указателя слота и подсчётом lease
- справочник xrt · tcp_server — режимы совместного использования слушающих socket