GRPC API

Начиная с GameAP 4.2 и GameAP Daemon 4.0 панель и демон обмениваются данными по gRPC через двунаправленный поток (bidirectional streaming). Этот способ пришёл на смену старому обмену по BINN и REST API.

Соединение устанавливает демон: он сам подключается к панели и держит один долгоживущий поток, по которому идёт всё — регистрация, heartbeat, метрики, задачи, команды, консоль, работа с файлами. Панель к демону не подключается и входящих портов на выделенном сервере не требует.

Настройка панели

Отдельной настройки для включения gRPC нет: сервер запускается всегда. Настраиваются только адрес, шифрование и ограничения.

Переменная По умолчанию Назначение
GRPC_PORT 31718 Порт, который слушает gRPC-сервер панели
GRPC_TLS_ENABLED true Шифрование соединения
GRPC_REQUIRE_MTLS false Требовать от демона клиентский сертификат
GRPC_EXTERNAL_HOST "" Адрес панели, который сообщается демону. Пусто — определяется из запроса
GRPC_EXTERNAL_PORT 0 Порт, который сообщается демону. 0 — берётся GRPC_PORT
GRPC_MAX_RECV_MSG_SIZE 10485760 Предельный размер входящего сообщения, байт
GRPC_MAX_SEND_MSG_SIZE 10485760 Предельный размер исходящего сообщения, байт
GRPC_MAX_CONCURRENT_STREAMS 100 Число одновременных потоков на одно соединение
GRPC_ENABLE_REFLECTION false Отражение схемы для отладочных утилит вроде grpcurl. В продакшене не включать

Переменной GRPC_ENABLED не существует — панель её не читает. Старые версии gameapctl дописывают строку GRPC_ENABLED=true в config.env: она безвредна, но ни на что не влияет. Выключить gRPC-сервер нельзя.

Порты

gRPC работает на отдельном порту 31718, веб-интерфейс и API — на HTTP_PORT (по умолчанию 8025). Это два разных слушателя, а не один порт с разбором протокола.

Порт 31718 должен быть доступен всем выделенным серверам. Это единственный порт панели, который нужен работающему демону.

В Dockerfile и docker-compose.yml панели опубликован только порт 8025. При развёртывании в Docker порт 31718 нужно пробросить самостоятельно.

Адрес панели для демона

Панель подставляет свой адрес в команду установки демона и в connect URL вида grpc://хост:порт/ключ. По умолчанию хост берётся из заголовка запроса, которым администратор открыл страницу создания выделенного сервера — то есть из адреса в адресной строке браузера.

Задавайте GRPC_EXTERNAL_HOST, если этот адрес не совпадает с тем, по которому демоны должны подключаться:

  • панель за обратным прокси, а gRPC через прокси не проходит и демоны должны идти напрямую;
  • панель за NAT, у неё разные адреса изнутри и снаружи;
  • панель в Docker, где в заголовке оказывается localhost или имя контейнера.

GRPC_EXTERNAL_PORT нужен, когда порт 31718 наружу опубликован под другим номером.

Если переменные не заданы, сам gRPC-сервер работает нормально — неправильным получается только адрес в сгенерированной команде установки, и демон не сможет подключиться.

GRPC_EXTERNAL_HOST попадает в список альтернативных имён (SAN) самоподписанного сертификата gRPC. Сертификат создаётся один раз при первом запуске, поэтому переменную нужно задать до первого старта панели. Если задать её позже, демон будет отклонять соединение из-за несовпадения имени в сертификате: удалите certs/server/api-server.crt и certs/server/api-server.key и перезапустите панель, чтобы сертификат сгенерировался заново.

Шифрование и сертификаты

При GRPC_TLS_ENABLED=true (значение по умолчанию) панель использует самоподписанный сертификат, выпущенный её собственным внутренним центром сертификации: certs/root.crt и certs/root.key. Сертификат сервера — certs/server/api-server.crt. Ключи RSA 2048 бит, срок действия 10 лет, всё создаётся автоматически при первом обращении.

Эти сертификаты никак не связаны с HTTPS-сертификатом самой панели: ACME и Let’s Encrypt на gRPC не распространяются, отдельно настраивать их не нужно.

При регистрации демон получает от панели ca.crt, server.crt и server.key и складывает их в свой каталог сертификатов. Дальше он проверяет сертификат панели по полученному CA и предъявляет свой клиентский сертификат.

Дополнительно каждый запрос аутентифицируется ключом API узла, который хранится в базе панели в виде SHA-256 и сравнивается за постоянное время.

Взаимная аутентификация (mTLS)

GRPC_REQUIRE_MTLS=true заставляет панель требовать от клиента сертификат, выпущенный её собственным центром сертификации, и отклонять запросы без него.

Специально настраивать демон для этого не нужно: зарегистрированный демон и так всегда предъявляет свой сертификат.

Включайте mTLS только после того, как все демоны зарегистрированы. Сама регистрация идёт без клиентского сертификата — у нового демона его ещё нет. При GRPC_REQUIRE_MTLS=true зарегистрировать новый выделенный сервер не получится. Чтобы добавить узел позже, временно верните false, зарегистрируйте демона и включите обратно.

Демоны, зарегистрированные другой панелью, работать не будут: их сертификаты выпущены чужим центром сертификации.

Настройка демона

Параметры подключения задаются в конфигурации демона — /etc/gameap-daemon/gameap-daemon.yaml в Linux, C:\gameap\daemon\gameap-daemon.yaml в Windows — в блоке grpc:

grpc:
  address: panel.example.com:31718
  insecure: false
  heartbeat_interval: 30s
  connect_timeout: 30s
  initial_reconnect_delay: 1s
  max_reconnect_delay: 60s
Параметр По умолчанию Назначение
address Адрес панели в виде хост:порт
insecure false Отключить TLS. Только для отладки
heartbeat_interval 30s Период отправки heartbeat. Панель может назначить своё значение
connect_timeout 30s Таймаут установки соединения
initial_reconnect_delay 1s Начальная пауза перед переподключением
max_reconnect_delay 60s Предельная пауза перед переподключением

Если address не задан, он выводится из устаревшего параметра api_host: берётся имя хоста, порт заменяется на 31718. Задавать address явно надёжнее.

Ключа grpc.enabled у демона тоже нет. gameapctl записывает его при миграции как отметку о том, что миграция выполнена; демон этот ключ игнорирует.

Остальные параметры конфигурации демона описаны на странице GameAP Daemon.

Переподключение и обрыв связи

Если соединение потеряно, демон переподключается сам, с экспоненциальной задержкой: она удваивается от initial_reconnect_delay до max_reconnect_delay и разбавляется случайным разбросом ±10 %, чтобы много демонов не пришли одновременно. При значениях по умолчанию это 1 с, 2 с, 4 с, 8 с и так далее до 60 с. После удачного подключения счётчик обнуляется. Панель при плановой остановке может сама назначить демону паузу перед следующей попыткой.

Пока панель недоступна, игровые серверы продолжают работать — прерывается только управление ими из панели. После восстановления связи демон заново регистрируется, сообщает о задачах, которые выполняет прямо сейчас, и получает от панели полное текущее состояние: список серверов, задачи, игры и модификации, настройки серверов. Поэтому задачи, начатые до обрыва, не теряются.

Механизм gRPC keepalive не используется ни на одной стороне: живость соединения держится только на heartbeat раз в 30 секунд. Если между демоном и панелью стоит NAT или межсетевой экран, который закрывает бездействующие соединения быстрее, уменьшите heartbeat_interval.

Возможности канала

По одному соединению идёт всё взаимодействие панели и демона. При регистрации демон сообщает список поддерживаемых возможностей, и панель по нему решает, что можно запрашивать.

Возможность Что обеспечивает
grpc Базовый обмен: регистрация, heartbeat, задания, команды
file_transfer Файловый менеджер: чтение каталогов, загрузка и скачивание файлов
server_status Состояние игровых серверов
attach Интерактивная сессия с игровым сервером и консоль
metrics Метрики выделенного сервера и игровых серверов
archive Упаковка и распаковка архивов на выделенном сервере
http_proxy HTTP-запросы через демона — см. ниже

Возможность отсутствует, если демон старой версии её не поддерживает: панель тогда не будет предлагать соответствующие действия.

HTTP-запросы через демона

Канал позволяет панели выполнять HTTP-запрос из сети выделенного сервера — включая обращения к unix-сокету на нём. Это нужно, чтобы дотянуться до служб, доступных только с выделенного сервера: панели управления игрой, локального API, сокета контейнерного движка.

Механизм реализован с обеих сторон и работает при нескольких экземплярах панели: запрос уходит тому экземпляру, который владеет соединением с нужным демоном.

В текущей версии панели этой возможностью ничего не пользуется. Демон сообщает http_proxy при регистрации, но ни один раздел интерфейса и ни один встроенный механизм запросов через него не делает. Считайте её заготовкой на будущее.

Переход со старого протокола

Демон, установленный до появления gRPC, переводится на новый протокол командой:

gameapctl daemon upgrade --switch-to-grpc

Что делает команда:

  1. Проверяет, что переход ещё не выполнялся, и определяет адрес панели из api_host (либо берёт его из --grpc-address).
  2. Проверяет, что в конфигурации есть api_key, ds_id и все три файла сертификатов.
  3. До внесения изменений проверяет доступность панели: устанавливает TCP-соединение и выполняет настоящее TLS-рукопожатие с имеющимися сертификатами. Если сертификаты выпущены другой панелью, команда об этом сообщит и предложит переустановку.
  4. Делает резервную копию конфигурации рядом с оригиналом, с отметкой времени в имени.
  5. Прописывает адрес gRPC и удаляет устаревшие api_host, listen_ip и listen_port.
  6. Перезапускает демона и убеждается, что панель отозвала доступ по старому HTTP API.
  7. При любой неудаче после шага 5 откатывает конфигурацию из резервной копии и запускает демона обратно.

Требуется только доступность порта 31718 панели с выделенного сервера. Никаких настроек на стороне панели включать не нужно — вопреки тому, что написано в сообщении об ошибке самой команды и в её описании, переменной GRPC_ENABLED не существует.

Проверка

Панель отвечает на стандартный gRPC health check и сообщает состояние SERVING для служб gameap.DaemonGateway и gameap.FileTransferService.

Простейшая проверка доступности порта с выделенного сервера:

nc -zv panel.example.com 31718

Состояние подключения демона видно в панели на странице «Администрирование»«Выделенные серверы». Подробности — в журнале демона: /var/log/gameap-daemon/output.log в Linux, C:\gameap\daemon\logs\output.log в Windows.

Типовые сообщения в журнале демона:

Сообщение Что означает
gRPC connection failed Соединение не установлено или разорвано, дальше идёт пауза и новая попытка
registration failed: ... Соединение есть, но панель отклонила регистрацию — неверный ds_id или api_key
Ошибка проверки сертификата Имя в сертификате панели не совпадает с адресом подключения. См. GRPC_EXTERNAL_HOST