Глава 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 как живое доказательство)
Дальнейшее чтение по xrt
  • xrt · x509 — разбор даты истечения сертификата (функция реестра)