[Подготовка в продакшен] Переход с polling на webhook для масштабирования в k8s #71

Open
opened 2026-05-13 22:02:40 +03:00 by Toutsu · 0 comments
Owner

Контекст

Сейчас бот работает через long-polling (TelegramBotServiceGetUpdatesAsync). При попытке развернуть GmRelayBot в Kubernetes (Minikube/прод) и масштабировать реплики возникает проблема: Telegram API не позволяет нескольким инстансам одновременно держать getUpdates на один токен — апдейты разойдутся между подами и часть сообщений потеряется.

Цель

Перевести механизм получения апдейтов с polling на webhook, чтобы обработка сообщений масштабировалась через стандартный k8s Ingress + HPA без shared state.

Текущая реализация

  • src/GmRelay.Bot/Infrastructure/Telegram/TelegramBotService.csBackgroundService с циклом GetUpdatesAsync
  • TelegramUpdateSource.GetUpdatesAsync — прямой вызов bot.GetUpdates(...)
  • В compose.yaml сервис bot единственный, нет ingress/web endpoint

Что нужно сделать

  1. Убрать polling-сервис
    • Удалить/отключить TelegramBotService (BackgroundService)
    • Убрать регистрацию ITelegramUpdateSource / TelegramUpdateSource
  2. Добавить webhook endpoint
    • MapPost("/webhook", ...) в Program.cs (или отдельный минимальный API проект)
    • Десериализация Update из POST body
    • Вызов того же UpdateRouter.RouteAsync(update, ct)
  3. Настройка Telegram
    • SetWebhookAsync при старте (URL + секретный токен для проверки подлинности)
    • DeleteWebhookAsync при graceful shutdown
  4. Инфраструктура (k8s)
    • Ingress с HTTPS (cert-manager / Let's Encrypt)
    • livenessProbe / readinessProbe на health endpoint
    • HPA на Deployment бота (CPU/RPS)
  5. Fallback / локальная разработка
    • Опционально: флаг UseWebhook=true/false в конфигурации, чтобы локально продолжать работать через polling без белого IP

Критерии приёмки

  • Локально (docker compose) бот продолжает работать либо через polling, либо через ngrok webhook
  • В k8s несколько реплик бота получают апдейты без потерь через Ingress
  • UpdateRouter и все существующие хендлеры не меняются (только точка входа)
  • Graceful shutdown корректно удаляет webhook

Связанные файлы

  • src/GmRelay.Bot/Program.cs
  • src/GmRelay.Bot/Infrastructure/Telegram/TelegramBotService.cs
  • src/GmRelay.Bot/Infrastructure/Telegram/TelegramUpdateSource.cs
  • compose.yaml

Примечание

Это блокер для этапа "Подготовка в продакшен" при переходе на Kubernetes.

## Контекст Сейчас бот работает через **long-polling** (`TelegramBotService` → `GetUpdatesAsync`). При попытке развернуть GmRelayBot в Kubernetes (Minikube/прод) и масштабировать реплики возникает проблема: Telegram API не позволяет нескольким инстансам одновременно держать `getUpdates` на один токен — апдейты разойдутся между подами и часть сообщений потеряется. ## Цель Перевести механизм получения апдейтов с polling на **webhook**, чтобы обработка сообщений масштабировалась через стандартный k8s Ingress + HPA без shared state. ## Текущая реализация - `src/GmRelay.Bot/Infrastructure/Telegram/TelegramBotService.cs` — `BackgroundService` с циклом `GetUpdatesAsync` - `TelegramUpdateSource.GetUpdatesAsync` — прямой вызов `bot.GetUpdates(...)` - В `compose.yaml` сервис `bot` единственный, нет ingress/web endpoint ## Что нужно сделать 1. **Убрать polling-сервис** - Удалить/отключить `TelegramBotService` (`BackgroundService`) - Убрать регистрацию `ITelegramUpdateSource` / `TelegramUpdateSource` 2. **Добавить webhook endpoint** - `MapPost("/webhook", ...)` в `Program.cs` (или отдельный минимальный API проект) - Десериализация `Update` из POST body - Вызов того же `UpdateRouter.RouteAsync(update, ct)` 3. **Настройка Telegram** - `SetWebhookAsync` при старте (URL + секретный токен для проверки подлинности) - `DeleteWebhookAsync` при graceful shutdown 4. **Инфраструктура (k8s)** - Ingress с HTTPS (cert-manager / Let's Encrypt) - `livenessProbe` / `readinessProbe` на health endpoint - HPA на Deployment бота (CPU/RPS) 5. **Fallback / локальная разработка** - Опционально: флаг `UseWebhook=true/false` в конфигурации, чтобы локально продолжать работать через polling без белого IP ## Критерии приёмки - [ ] Локально (docker compose) бот продолжает работать либо через polling, либо через ngrok webhook - [ ] В k8s несколько реплик бота получают апдейты без потерь через Ingress - [ ] `UpdateRouter` и все существующие хендлеры не меняются (только точка входа) - [ ] Graceful shutdown корректно удаляет webhook ## Связанные файлы - `src/GmRelay.Bot/Program.cs` - `src/GmRelay.Bot/Infrastructure/Telegram/TelegramBotService.cs` - `src/GmRelay.Bot/Infrastructure/Telegram/TelegramUpdateSource.cs` - `compose.yaml` ## Примечание Это блокер для этапа "Подготовка в продакшен" при переходе на Kubernetes.
Toutsu added this to the Подготовка к production milestone 2026-05-13 22:03:37 +03:00
Toutsu modified the milestone from Подготовка к production to Этап — Kubernetes / k8s Production 2026-05-13 22:07:32 +03:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Toutsu/GmRelayBot#71