Глава 7 / 51
Том 2 · Конфигурация и сборка

xs.json подробно · поля уровня сервиса

xs.json — единственный интерфейс сборки XServer. Глава разбирает каждое предустановленное поле services[i] — не только «как писать», но и «что произойдёт при ошибке».

Обзор

Позиционирование: том 2 начинается с уровня сервиса — он определяет, «сколько слушателей в процессе и на каком протоколе каждый». Глава идёт в паре со справочной страницей полей: учебник объясняет принципы и границы, справочник — для быстрого поиска. Кто уже запускал демо, может пробежать 7.2 / 7.4.

7.1 Введение

У конфигурационных систем две типовые болезни. Первая — расхлябанность: поле с опечаткой молча игнорируется и всплывает только в продакшне. Вторая — рассеяние: поведение размазано по конфигам, переменным окружения и командной строке. Ответ xs.json — fail-fast и единый источник: любое недопустимое предустановленное поле называется и отклоняется при старте, а любое непредустановленное поле без изменений уходит в Custom приложению — поле, которого хост не знает, никогда не проглатывается и никогда не получает угаданного смысла.

7.2 Пять классов протоколов (class)

classСемантикаКолбэки скрипта
httpHTTP/1.1 + HTTPS (переключатель TLS)RequestProc
wsWebSocket + WSSWsOpen/Text/Binary/Ping/Pong/Close
tcpГолый поток / поток TLSEventOpen/Data/Close
udpДейтаграммы (без TLS)EventDgram
customСобытийный собственный сервисОпределяет приложение (через вход Engine)

Значения вне белого списка сразу fail-fast. Критерий выбора прост: что говорит браузер — http/ws; байтовые потоки — tcp; без соединений — udp; остальное делайте сами.

7.3 Поля эндпоинтов

Комбинация полей эндпоинта
{
    "ip": "0.0.0.0",        /* адрес прослушивания, по умолчанию все интерфейсы */
    "port": 80,             /* порт открытого текста, обязателен кроме custom */
    "tls": true,            /* включить TLS-порт; для udp запрещено */
    "port_tls": 443,        /* по умолчанию 443; конфликт с портом открытого текста на том же IP отклоняется */
    "ip_tls": "0.0.0.0"     /* по умолчанию совпадает с ip */
}

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

7.4 Поля лимитов

ПолеНазначениеОграничение
backlogОчередь прослушивания (напрямую в xrt)Проверка диапазона uint32
recv_limitПредел одного чтения потока≤SIZE_MAX; на udp ≤65535

recv_limit — линия обороны памяти: потолок данных, втягиваемых за одно чтение. На tcp он формирует пик буфера соединения; на udp дейтаграммы по природе ≤64 КБ, поэтому потолок ужат до 65535. Запросные лимиты header/body — не предустановленные поля сервиса: это ручки Custom (глава 9), их читает http-драйвер.

7.5 Скриптовые умолчания уровня сервиса

Пять скриптовых полей можно указать на уровне сервиса как умолчания для всех хостов:

Скриптовые умолчания сервиса → синтез DefaultHost
{
    "class": "http",
    "name": "my-site",
    "port": 8080,
    "path": "wwwroot",       /* корень статики */
    "devlang": "c",          /* язык скрипта */
    "devfile": "main.c",     /* вход скрипта */
    "dev_inc": "includes",   /* доп. каталоги заголовков (через точку с запятой) */
    "dev_lib": "librarys"    /* доп. каталоги библиотек */
}

Если host_default не задан, эти пять полей синтезируют DefaultHost — именно поэтому минимальному приложению главы 4 host_default не понадобился. Одноимённые поля уровня хоста переопределяют по одному.

7.6 Контракт

  • Валидация: белый список class, port 1–65535, взаимоисключение tls×udp, конфликты портов — всё называется и уходит в fail-fast при старте.
  • Умолчания: скриптовые поля уровня сервиса — лишь источник умолчаний для уровня хоста, не вторая система конфигурации.
  • Уникальность: name глобально уникален — это ключ xsServerFind в рантайме и описание цели reload.

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

Конфликт портов принят за «проблему среды»
Симптом
Старт падает; ошибка называет конфликт портов открытого текста и TLS.
Причина
port и port_tls совпадают на одном IP (или каждый сталкивается с другими сервисами).
✗ Ошибка
{ "ip": "0.0.0.0", "port": 8080,
  "tls": true, "port_tls": 8080 }
✓ Правильно
{ "ip": "0.0.0.0", "port": 8080,
  "tls": true, "port_tls": 8443 }
UDP-сервису назначили TLS
Симптом
Старт падает: tls on udp.
Причина
UDP — дейтаграммный протокол; XServer не строит TLS поверх UDP — защищённый UDP-транспорт остаётся за приложением (например, соберите DTLS-подобную схему сами).
✗ Ошибка
{ "class": "udp", "port": 9000,
  "tls": true }
✓ Правильно
{ "class": "udp", "port": 9000 }

Упражнения

БазовыйПо одному каждого класса

Напишите xs.json с четырьмя сервисами — http (8080), ws (8081), tcp (8082), udp (8083) — все работоспособны на варианте default (скрипты могут ничего не экспортировать).

Приёмка: в логе старта четыре строки bound; Ctrl+C — корректный выход.
ПродвинутыйВызвать все проверки эндпоинтов

По очереди создайте: port вне диапазона, port отсутствует, конфликт портов открытый текст/TLS, tls on udp — зафиксируйте каждое сообщение.

Приёмка: все четыре сообщения соответствуют правилам 7.3, ни одного «расплывчатого провала».
ВызовНаблюдение двух эндпоинтов под нагрузкой

Включите TLS-порт у http-сервиса с сертификатом (подойдут тестовые сертификаты репозитория home), обратитесь curl'ом к обоим эндпоинтам и сравните поведение рукопожатия.

Приёмка: вы можете объяснить поведение TLS-эндпоинта при открытом запросе (подсказка: байты попадают в TLS-разбор как поток; глава 22 использует это явление).

Итоги

ТезисВывод
Пять классовhttp / ws / tcp / udp / custom; белый список fail-fast
ЭндпоинтыДва эндпоинта: открытый текст + TLS; конфликт на одном IP отклоняется
Лимитыbacklog напрямую в xrt; recv_limit на udp ≤65535
Скриптовые умолчанияПять полей сервиса синтезируют DefaultHost; уровень хоста переопределяет по одному
Шпаргалкасправочник полей ref-config
Что дальше по xrt