Перейти к содержанию

Масштабирование v2

В данной статье описываются принцип работы и настройка масштабирования на Webim Server версий 10.5–10.7 (включительно).

Масштабирование Webim Chat Backend

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

Масштабирование (кластеризация) предусматривает запуск дополнительного числа экземпляров бэкенда и распределение приходящей нагрузки между ними. Теоретически количество одновременно запущенных экземпляров Chat Backend неограничено, но запуск более 6 экземпляров не рекомендуется.

Внимание!

Данная версия масштабирования не предоставляет fault tolerance: аварийное отключение slave-узла приведёт к частичной деградации сервиса, а последствием отключения master-узла будет полная остановка работы.

Масштабирование является асимметричным, то есть нагрузка между серверами распределяется неравномерно. В частности, задачи, относящиеся ко многим сессиям посетителей и операторов (например, автоназначение чатов), реализуются только на одном из серверов (master). Задачи, относящиеся к одной сессии (например, отправка сообщения), выполняются на «домашнем» узле этой сессии (обычно slave-узле).

В каждом кластере должен быть один master-узел и не менее одного slave-узла. Master-узел выполняет задачи, которые не могут быть распределены между несколькими узлами, например автоназначение чатов на операторов. Сессии операторов и посетителей распределяются по slave-узлам, и каждый slave-узел выполняет задачи, относящиеся к сессиям, для которых он является домашним (например, смена статуса оператора или добавление нового сообщения в чат). Принципиально ничего не мешает размещать часть сессий на master-узле, но для симметрии и чтобы разгрузить master, это обычно не делается.

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

Привязка сессий к узлам и маршрутизация запросов

Сессии операторов и посетителей привязаны к конкретному узлу кластера (к «домашнему» узлу сессии). При этом на уровне балансировщика sticky sessions не используются и не требуются.

Маршрутизация устроена следующим образом:

  1. Внешний балансировщик (например, nginx) распределяет входящие запросы на любой доступный узел кластера.

  2. Узел, получивший запрос, определяет «домашний» узел целевой сессии.

  3. Если запрос пришёл не на домашний узел, он проксируется внутри кластера на домашний узел, а результат возвращается инициатору запроса.

Следствия такого подхода:

  • Узлы кластера должны иметь сетевую связность между собой (внутрикластерный трафик), иначе проксирование запросов будет невозможно.

  • Возможна дополнительная задержка из-за «лишнего хопа» (узел A принял запрос и переслал его на узел B).

  • Даже если входящий запрос попал на «живой» узел, операции сессии всё равно зависят от доступности её домашнего узла.

Что происходит при отказе узлов

  • Отказ slave-узла приводит к недоступности/ошибкам для сессий, домашним узлом которых был этот slave. Другие сессии, закреплённые за оставшимися узлами, продолжают работать. Даже если балансировщик перестанет отправлять прямые запросы на упавший slave, проксирование запросов на домашний узел для этих сессий также будет невозможным.

  • Отказ master-узла приводит к полной остановке работы кластера, так как функции, реализованные только на master (например, автоназначение), становятся недоступны.

Настройка RabbitMQ

Предварительным условием для запуска масштабирования является наличие установленного RabbitMQ, доступного всем узлам кластера Chat Backend по сети. Инструкцию по установке вы можете найти в официальной документации.

N.B.

При желании вы также можете добавить административную панель, отображающую текущее состояние сервиса. Это может пригодиться для мониторинга. Сделать это вы можете, выполнив следующую команду:

rabbitmq-plugins enable rabbitmq_management

Перезагрузка сервиса при этом не требуется.

Кто создаёт очереди/обменники/биндинги

Внутреннюю инфраструктуру внутри RabbitMQ (обменники, очереди, биндинги и т. п.) создаёт приложение (Chat Backend) автоматически при старте, в рамках указанного virtual host.

Со стороны администратора требуется только:

  • создать virtual host (vhost), который будет использоваться кластером;

  • создать пользователя и пароль;

  • выдать пользователю права на vhost;

  • обеспечить сетевую доступность RabbitMQ с узлов Chat Backend.

Ручное создание очередей/биндингов администратором не требуется.

Минимальная конфигурация RabbitMQ

Дополните конфигурационный файл RabbitMQ /etc/rabbitmq/rabbitmq.conf следующими параметрами:

listeners.tcp.default = <port>
management.tcp.port = <port>
default_user_tags.administrator = true
default_user = <username>
default_pass = <password>
loopback_user = none

Здесь:

  • listeners.tcp.default — порт прослушивания запросов к RabbitMQ

  • management.tcp.port — порт, по которому предоставляется доступ к административной панели RabbitMQ (при наличии плагина rabbitmq_management)

  • default_user — имя пользователя RabbitMQ

  • default_pass — пароль пользователя RabbitMQ

Настройка масштабирования

Для запуска масштабирования необходимо изменить конфигурацию nginx. Ниже приведена подробная инструкция.

  1. Создайте новый конфигурационный файл в директории /etc/nginx/sites-available/ для хранения в нём настроек балансировщика нагрузки.

  2. В созданном файле укажите IP-адреса, на которых будут развёрнуты экземпляры Chat Backend. Файл должен иметь следующий вид:

upstream chat_backend {
server <IP address 1>:<port 1>;
server <IP address 2>:<port 2>;
server <IP address 3>:<port 3>;
...
server <IP address N>:<port N>;
}

Значения портов могут совпадать.

  1. Сохраните изменения и откройте файл /etc/nginx/sites-available/webim.conf. В его начало добавьте следующее:
include </path/to/file.conf>;

Здесь </path/to/file.conf> — путь к ранее созданному файлу.

  1. В том же файле замените proxy_pass 127.0.0.1:<port> на proxy_pass http://chat_backend в следующих локациях:

    • \/l\/button\.php

    • \/ws\/

    • \/l\/(v|o)\/download.*\.(png|gif|jpe?g|svg|webp|pdf|doc)$

    • \/l\/(v|o)\/download\/.*?([^\/]+)$

    • \/l\/v\/

    • /l/o/get-operator-statuses

    • \/l\/

    • \/api\/v\d+\/(chats|operators|departments|chat|tariffs|stats|categories)

    • \/api\/v\d+\/(rt|file|wm_notification|visitor|robot_post_message)

    • ^\/api\/stc-bot\/

Настройка кластера

В параметрах запуска чат-сервера нужно указать:

  • --node_name — имя узла. Оно должно содержаться в списке узлов, указываемых в конфигурации кластера. В рамках одного кластера нельзя запускать два узла с указанием одного и того же имени.

  • --cluster_config — путь к json-файлу, содержащему конфигурацию кластера вида:

{
"cluster_name": "default",
"chat_server_node_names": ["master", "slave8270", "slave8271"],
"chat_server_master_node_name": "master"
}

Конфигурация содержит:

  • cluster_name — имя кластера

  • chat_server_node_names — список имён всех узлов кластера

  • chat_server_master_node_name — имя выделенного master-узла в кластере, выполняющего функции, которые нельзя распределить по разным узлам (например, автоназначение чатов); должно содержаться в списке chat_server_node_names

Конфигурация должна быть одинаковой для всех узлов в кластере. Для узлов, запускаемых на одном хосте, предполагается использовать один и тот же файл; для разных хостов — его копии.

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

  • mq_host — имя / IP-адрес хоста RabbitMQ

  • mq_port — порт подключения к RabbitMQ (значение параметра listeners.tcp.default из /etc/rabbitmq/rabbitmq.conf)

  • mq_username — имя пользователя RabbitMQ (значение параметра default_user из /etc/rabbitmq/rabbitmq.conf)

  • mq_password — пароль пользователя RabbitMQ (значение параметра default_pass из /etc/rabbitmq/rabbitmq.conf)

  • mq_virtual_host — имя virtual host на стороне RabbitMQ. Vhost должен быть создан заранее, а пользователю mq_username должны быть выданы права на этот vhost.

Для удобства администрирования рекомендуется добавить параметр mq_node_id_prefix в дополнительный конфигурационный файл webim_mq.ini, размещаемый в поддиректории main.ini.d.

Отключение масштабирования Chat Backend

Для отключения масштабирования Chat Backend необходимо совершить следующие действия:

  1. Выключить все узлы кластера.

  2. Убрать из конфигурации nginx настройки, добавленные для включения масштабирования (см. выше).

  3. Запустить Chat Backend без параметров масштабирования.


Последнее обновление: 23 января 2026 г.