Балансировщик websocket запросов. Архитектура такова:
Есть комната, к которой подключается пользователь.
Есть несколько нод приложения. Запрос должен распределиться на ту ноду, где эта комната создана.
У каждой ноды есть одна из 3х ролей - Лидер, Кандидат и Воркер. При запуске нода идет в редис и проверяет список авторизованных нод. Если список пустой, то первая добавившаяся нода нарекается лидером, последующая смотрит, если лидер есть и нет кандидата, нарекается кандидатом, все остальные смотрят, если лидер и кандидат существует, нарекается воркером.
Лидер следит за нагрузкой на нодах (активные соединения) и при необходимости проводит ребалансировку (когда надо перенести коннекты к чату, если они разрастаются, а подключений к ноде уже не хватает). Для этого он должен реализует следующий флоу:
Посмотреть доступный ресурс среди имеющихся воркеров в редис и при необходимости запросить создание нового ресурса (еще одной ноды для ребалансировки)
Послать сигнал ноде, которая обслуживает соединения по событию, чтобы произвела редирект всех соединений на созданную/выбранную ноду для ребалансировки
При необходимости - утилизация освободившейся ноды (если текущий ресурс на N% больше от нагрузки)
Кандидат следит за работой лидера, берет на себя функцию при его падении и нарекает нового кандидата из списка воркеров.
Флоу ноды таков:
Обрабатывает входящее соединение.
Смотрит, есть ли на текущей ноде нужная подписка на событие(в локальном кеше). Если событие существует, то начинает обслуживать соединение и отправлять сообщения по событию. Добавляет в редис инкремент по количеству подключений на ноду и на одно событие, а также заносит запись отношения события к ноде.
Если необходимой подписки на событие в текущей ноде нет, то идем в редис и ищем среди отношений события к ноде нужную нам ноду по ИД события, который передается во входящем запросе.
Если находим нужную ноду, то редиректим соединение на эту ноду.
Если нужной ноды нет (событие новое), то идем в редис, запрашиваем инфу по загрузке и смотрим, какая нода подходит для распределения с учетом минимального резерва, далее либо редиректимся на нужную ноду, либо остаемся на текущей.
Создание события.
При создании события подписываемся на прослушивание очереди
При текущей схеме мне не понятно, как решить роутинг до конкретного пода в кубернетесе. Обычный round-robin здесь, очевидно, не подходит.
Непонятно, почему вы решили, что это должен делать Kubernetes.
Это выглядит как логика самого сервиса и ваше приложение должно решать подобные вопросы.
Alexey Dmitriev, ну вот я, в идеале, вижу такую штуку, как sticky-session только до пода:
1. Запрос /chat прилетает в ингресс и прокидывается на под my-service-zxcv
2. Под my-service-zxcv понимает, что этот юзер должен быть на поде my-service-asd и ставит куку pod=my-service-asd и делает редирект на себя же, то есть на /chat
3. Запрос /chat прилетает в ингресс, ингресс видит, что есть кука pod=my-service-asd и кидает запрос в этот под, если куки нет, то и включается обычный лоад балансер.