Сейчас идёт тестирование: код на 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
  • Зарегистрируйте в клиенте (брокере) адреса всех узлов, чтобы переключение при отказе происходило автоматически. Использование для конкретных языков смотрите в Библиотеках.