Сейчас идёт тестирование: код на GitHub будет открыт после завершения.

Развёртывание сервера Ticketing

Окружение
Оболочка
Режим
bash
Пример подключения клиента
rust
Быстрый тест через nc
bash

Переменные окружения

Настройка сервера производится полностью через переменные окружения. Ключи регистронезависимы, пустое значение считается неустановленным, а флаговые значения истинны только при 1/true/yes/on. Образ Docker основан на scratch, поэтому конфигурация внедряется исключительно через переменные окружения, без файла конфигурации.

Переменная окруженияПо умолчаниюОписание
PORT5225порт прослушивания в одиночном режиме. Игнорируется в режиме кластера — вместо него используется порт из CLUSTER_SELF
SOCKET_BIND0.0.0.0адрес прослушивания
CLIENT_TOKENS(нет)список токенов аутентификации клиентов через запятую. Если не задан, разрешён пустой токен
CLUSTER_SELF(нет)публикуемый адрес этого узла, host:port. Наличие включает режим кластера
CLUSTER_PEERS(нет)список публикуемых адресов всех узлов через запятую. Ровно 3 или 5, в одинаковом порядке на каждом узле, обязательно включает self
CLUSTER_TOKENS(нет)список токенов аутентификации между пирами через запятую
TLS_CERT / TLS_KEY(нет)пути к PEM-файлам сертификата/приватного ключа — задайте оба вместе, чтобы включить TLS
TLS_CA(нет)CA для проверки сертификатов пиров — если не задан, используется системное хранилище доверия
TLS_SKIP_VERIFYfalseпропуск проверки сертификата пира — только для тестов
DOCKERfalseфиксирует внутренние порты прослушивания как 5225/6225 в режиме кластера — включено по умолчанию в официальном образе
DEBUGзависит от сборки1/true включает debug-логи

Полные правила (вывод порта, публикуемые адреса, замена токена без простоя и т. д.) смотрите в Конфигурация (переменные окружения).

Одиночный режим vs. кластер

  • Одиночный (1 узел): без CLUSTER_* узел работает автономно. Самый быстрый вариант, но при перезапуске бывает короткий сбой, а состояние хранится в памяти и теряется при перезапуске (lease — страховочная сеть).
  • Кластер (непрерывный): 3 или 5 узлов. Узлы разделяют единое состояние блокировок через консенсус Raft — запросы обрабатывает только лидер, и каждое изменение состояния фиксируется только после commit большинством. Если лидер умирает, новый избирается за 0,5–1 секунду, и пока сохраняется большинство, состояние блокировок и обслуживание продолжаются. Полное объяснение смотрите в Как это работает и Протокол (кластер).
  • Каждый узел кластера слушает клиентский порт плюс Raft-порт (клиентский порт + 1000) — откройте оба порта в брандмауэре.

Развёртывания кластера в Kubernetes используют StatefulSet + headless Service. Дайте каждому поду стабильное DNS-имя (ticketing-0.ticketing…, ticketing-1.ticketing…), внесите эти имена в CLUSTER_PEERS, а CLUSTER_SELF каждого пода автоматически внедряйте через downward API (metadata.name).

Непрерывный перезапуск (rolling)

Есть одно ключевое правило — большинство должно оставаться в строю всегда (не более 1 из 3 одновременно недоступно).

  1. Перезапускайте сначала followers, по одному. Как только перезапущенный узел догонит состояние через репликацию или снапшот, переходите к следующему.
  2. В последнюю очередь выводите лидера — новый избирается за 0,5–1 секунду, и клиенты переключаются прозрачно.
  3. Повторный подъём выведенного узла присоединяет его как follower.

Подробные шаги смотрите в Процедуре непрерывного перезапуска.

Справка

  • Образ: sarolab/ticketing · Github: saro-lab/ticketing
  • Зарегистрируйте в клиенте (брокере) адреса всех узлов, чтобы переключение при отказе происходило автоматически. Использование для конкретных языков смотрите в Библиотеках.