Как продавать шкуры и ловить троллей в Telegram с помощью Kafka, Kubernetes, PostgreSQL и Redis

Kate

Administrator
Команда форума

С чего все началось​

Работаю в IT больше 15 лет. Чем только не занимался, но всегда следовал правилу - каждые майские праздники я пытаюсь применить на практике что-то новое.

В этом году я прочитал книгу Event Driven Microservices и загорелся потрогать Kafka как настоящий брокер событий, а не сообщений.

Идей было много, но мне хочется проверить все это под реальной нагрузкой, что сразу привело в телеграм боты, где получить +- 1000 пользователей труда не составляет.

Я все детство провозился с ASCII играми в DOS и идея пришла сама собой. В телеграме я нашел кучу текстовых квестов, но с графикой не было ни одного. Я провел небольшое исследование, как телеграм реагирует на большое количество emoji и выявил пару проблем:

  • Есть ограничение на 13 символов в строке, до момента, как телега не будет все ломать
  • На андроид, начиная с 50 символа телеграм меняет стилистику emoji
Первое решается легко, а второе потребовало добавить шапку из элементов:

Я решил использовать синие ромбы, похоже на небо
Я решил использовать синие ромбы, похоже на небо
Когда с идеей определился, настал момент выбирать технологии к реализации:

  • У меня есть кластер Kubernetes и несколько серверов
  • Для хранения данных я установил PostgreSQL, так как хорошо его знаю
  • Написал несколько скриптов на "Bashsible" для потребностей DevOps
  • Установил Kafka. Версия с Zookeeper и без репликации
  • В дальнейшем добавил Redis, но об этом позже
  • Сервисы решил писать на Java со Spring Boot
  • Для хранения и аналитики логов поставил ELK
Первая проблема с которой я столкнулся - это настройка Webhook в телеграме. Он категорически отказывался принимать мой сертификат с ingress контроллера. Хотя, любой frontend сервис, размещенный на кластер, отлично работал в браузере через https.

Я провозился несколько часов, пока не понял в чем дело. Необходимо загрузить в tls секрет всю цепочку сертификатов. Спасибо доброму человеку, написавшего эту статью: Сшиваем SSL-сертификаты

Вторая - это ограничения Telegram. В первой версии я реализовал MMO. Персонажи обновлялись сразу во всех чатах, где их можно увидеть.

Но лимиты телеграма быстро вернули меня в реальность и я решил оставить эту затею. Затем пришла пора входного потока событий. Если изменять сообщение чаще чем раз в секунду, то сразу попадаешь под ошибку подобную этой:

Too Many Requests: "{"ok":false,"error_code":429,"description":"Too Many Requests: retry after 33","parameters":{"retry_after":33}}"
К этому моменту я разбил всю систему на 3 группы микросервисов:

  1. Получение событий из Telegram. Сервис обладает POST контроллером для получения действий пользователя из чата с ботом. А также Kafka Producer, отправляющего данные сообщения в обработку. Позже, я добавил к этому сервису Redis для проверки частоты кликов пользователя на кнопки в боте
  2. Обработчики событий. В нее входят:
    1. Consumer сообщений из входного потока сообщений, и producer в выходной поток сообщений
    2. Сервисы карты мира
    3. Объекты для взаимодействия (мобы, NPC, здания, лут и т.д.)
    4. Пользователи и их характеристики
    5. Квестовый движок (Состояния, диалоги, скрипты)
  3. Отправка событий в Telegram. Сервис получает сообщения из выходного потока и отправляет их в телеграм. Попутно проверяя их на лимиты.

Для чего пригодился Redis​

Я искал способ на проверку частоты отправки и наткнулся на такую возможность Redis как PX, т.е. время жизни объекта. При получения события я проверяю на наличие объекта по ключу(id чата пользователя), а затем записываю его опять с параметром px = 1000ms.

Если при получении события объект в Redis существует, то я игнорирую данное событие.

Ключевые фишки PostgreSQL​

PostgreSQL очень помог на этапе создания квестового движка. Я активно использую индексы с условием и функциональные констрейнты.

Также, очень помогла и сократила размер кода такая конструкция в запросах как INSERT ... on conflict do

Результат​

Я получил горизонтально-масштабируемую систему, позволяющую довольно легко внедрять новый функционал. При повышении нагрузки - я добавляю партиции в топики Kafka и увеличиваю кол-во pod'ов, содержащие consumer’ы.

Я накидал небольшой сюжет и опубликовал все это на нескольких ресурсах. Полет нормальный, народ требует продолжения, MMO и PvP

 
Сверху