Глава 47 / 51
Том 5 · Расширения, эксплуатация и практика
Практика 3: ферма сайтов на множестве vhost (реплика home)
Одним процессом управляем целой фермой сайтов — последняя практика берёт темой саму «форму развёртывания»: строим пятисайтовую смешанную ферму по производственным стандартам.
Обзор
Позиционирование: выпускной проект эксплуатационного направления. Гл. 20 дала метод организации; здесь проходим весь цикл по производственным стандартам — образцом служит репозиторий home (реальная продакшн-ферма из 14 vhost; мы строим учебную версию из пяти сайтов).
47.1 Цель проекта
| Сайт | Тип | Что отрабатываем |
|---|---|---|
| default (страховка) | статическая страница-навигатор | дисциплина страховки с минимальным риском (гл. 20) |
| www основной сайт | динамический (скрипт + шаблон + БД) | подключение результата Практики 1 |
| api поддомен | динамический (REST) | разводка по доменам + независимые лимиты |
| docs сайт документации | чистая статика (devlang=static) | форма сайта без скриптов |
| admin сайт управления | динамический (привязка к интрасети) | изоляция плоскости управления (гл. 27/39) |
47.2 Сборка фермы
- Раскладка: соглашение о самодостаточных каталогах host из гл. 20/37 — пять каталогов + один xs.json + один exe
- Конфигурация: один server с двумя конечными точками (80/443), принимающий всё; у пяти host — свои домены, сертификаты и ручки Custom (на сайте api ужесточаем body_limit; сайту docs — четыре ручки статического слоя)
- Общие модули: www и api переиспользуют modules/ (копированием, гл. 20) — важно, что имена ключей Custom на двух сайтах не мешают друг другу
- admin вне публичной сети: домен admin не попадает в публичный DNS + ограничение исходных IP на файрволе + токен (три эшелона обороны)
Приёмка 1: каждый из пяти сайтов попадает точно в цель (проверка заголовком Host / SNI); нераспознанные домены падают на страницу-навигатор default; на сайте docs — ноль следов скриптов в процессе (ни одной строки «script loaded»).
47.3 Горячая перезагрузка одного сайта
Дисциплина горячей перезагрузки фермы — «минимальный радиус поражения»:
- Повседневно: submit только целевого host (/admin/reload сайта admin → xsReloadHostSubmit)
- Проверка: остальные четыре сайта под постоянной нагрузкой — ноль ошибок, ноль ощущаемых изменений (незатронутые сайты вообще не участвуют — разводка на уровне конфигурации из гл. 20)
- Каскадные обновления: если изменение общего modules/ задевает несколько сайтов — reload по очереди, сайт за сайтом (не all) — прокатка, а не строй
- Тренировки: продление сертификата (замена сертификата сайта docs без единого разорванного соединения), откат плохого скрипта (отправляем битый скрипт на api → FAILED → старая версия не пострадала)
Приёмка 2: три подряд одиночных reload под нагрузкой на четырёх сайтах — без единого сбоя; горячая замена сертификата подтверждена сравнением через openssl.
47.4 Единая инспекция и сертификаты
- Маршрут инспекции: сайт admin реализует /status — перечисляет все server/host и выводит RunState, номер поколения и счётчики запросов (API запросов из гл. 11 + шаблоны гл. 43)
- Реестр сертификатов: /status прикладывает дату истечения сертификата каждого host (разбор x509) — напоминания о продлении уходят в операционный календарь
- Агрегация логов: у логов всех пяти сайтов единый префикс [имя сайта]; на стороне journald фильтруем по сайту
47.5 Лист приёмки
| Измерение | Критерий |
|---|---|
| Маршрутизация | все пять сайтов в точку + страховка default + согласованность трёх источников |
| Изоляция | reload одного сайта — ноль побочных эффектов; ключи Custom не мешают друг другу |
| Безопасность | три эшелона обороны на admin; весь чек-лист 44.4 пройден |
| Эксплуатация | работают маршрут инспекции / реестр сертификатов / логи по сайтам |
| Развёртывание | systemd + окно остановки + скрипт blue-green (результат задачи из гл. 42) |
Частые ошибки
Всё разом через all
- Симптом
- Чтобы поменять текст на одном сайте, отправляют xsReloadAllSubmit — и все пять сайтов меняют поколение.
- Причина
- all — пакетная транзакция для «глобальных изменений конфигурации» (гл. 26), а не ленивая рукоятка по умолчанию. Смена поколения на всей ферме = многократная компиляция + несколько проходов GC, каждый риск умножается.
Общий модуль забыли синхронизировать между сайтами
- Симптом
- Баг ReplyJSON починили на www, а api работает на старой версии.
- Причина
- Цена переиспользования копированием (гл. 20) — у каждого изменения общего модуля должен быть «список затронутых» (какие сайты его скопировали), и по нему прокатываем сайт за сайтом.
Упражнения
БазаПять сайтов в строю
Соберите ферму по 47.2 и пройдите приёмку 1.
Приёмка: приёмка 1 пройдена полностью.
ПродвинутыйЭксплуатационный контур
Выполните 47.3/47.4: горячая перезагрузка одного сайта + маршрут инспекции + реестр сертификатов.
Приёмка: приёмка 2 пройдена полностью; /status предупреждает о сертификатах, истекающих в течение 30 дней.
ВызовРасширить до четырнадцати сайтов
По реальному списку home расширьте ферму до 14 vhost (включая несколько чисто статических) и проверьте, что конфигурация и процессы масштабируются.
Приёмка: старт < 3 с; маршрут инспекции покрывает все сайты; эксплуатационная документация обновлена.
Итоги
| Пункт | Вывод |
|---|---|
| Форма | пять сайтов в одном процессе: статика и динамика разделены, управление в интрасети |
| Дисциплина перезагрузки | минимальный радиус поражения: submit по сайту, общие изменения — прокаткой |
| Эксплуатация | маршрут инспекции + реестр сертификатов + логи по сайтам |
| Проверка масштабом | учебные пять → производственные 14 (home как живое доказательство) |
Справочник API этой главы
Дальнейшее чтение по xrt
- xrt · x509 — разбор даты истечения сертификата (функция реестра)