Требования к серверам iQBot
Из чего состоит установка
iQBot состоит из нескольких процессов, которые работают с одной базой данных PostgreSQL:
| Компонент | Что делает | Порт по умолчанию | Нужен снаружи |
|---|---|---|---|
| iQBot (ядро и Studio) | Диалоговый движок, административная консоль, Studio, API для iQChannels. Studio работает отдельным процессом и доступна через порт ядра. | 3000 (Studio: 4000, внутренний) | Да, только порт 3000 |
| iQBot NLU | Распознавание намерений и сущностей, обучение моделей. | 3200 | Нет |
| Языковой сервер | Языковые модели (векторы слов) для NLU. Запускается отдельной командой, см. Установка iQBot на Linux. | 3150 | Нет |
| iQBot Messaging | Хранение бесед и сообщений, доставка событий. | 3100 | Нет |
| PostgreSQL | Данные ботов, диалоги, модели NLU. | 5432 | Нет |
| Duckling (по желанию) | Извлечение системных сущностей: время, числа, суммы, e-mail. Поставляется образом iqbot-platform/duckling. | 8000 | Нет |
Ядро запускает NLU и Messaging само, из каталога bin рядом с исполняемым файлом. Если порт занят, процесс выбирает ближайший свободный (для самого ядра в журнал пишется предупреждение). Языковой сервер и Duckling ядро не запускает.
Раньше языковой сервер по умолчанию слушал порт 3100, тот же, что Messaging, и на одном сервере их приходилось разводить ключом --port. В текущих сборках языковой сервер по умолчанию слушает 3150. Если вы обновляете установку, где порт задан явно, ничего менять не нужно.
Ресурсы компонентов
Таблица показывает, сколько оперативной памяти и дискового пространства занимает каждый компонент в работающей установке: один бот, русский язык, процессы после обучения модели. При обучении потребление памяти выше, поэтому в конфигурациях ниже оно взято с запасом.
| Компонент | Оперативная память | Диск |
|---|---|---|
| Ядро и Studio (два процесса) | около 0,7 ГБ в покое, 1,6–1,9 ГБ под нагрузкой, пики до 2,8 ГБ | дистрибутив около 1 ГБ вместе с NLU и Messaging |
| NLU: сервер и три рабочих процесса обучения | около 2 ГБ | модели хранятся в базе данных |
| Языковой сервер | зависит от размерности векторов, см. ниже: при размерности 100 закладывайте 1,3 ГБ на язык | при размерности 100 около 1 ГБ файлов на язык |
| Messaging | около 0,3 ГБ | |
| PostgreSQL | от 0,2 ГБ, растёт с данными | зависит от числа диалогов |
Память ядра под нагрузкой растёт, пока процесс не выполнит сборку мусора, затем падает: график похож на пилу с размахом около 1 ГБ. Закладывайте для узла с ядром и Studio не менее 3 ГБ свободной памяти.
Память языкового сервера и размерность векторов
Языковой сервер держит в памяти векторы слов каждого языка. Их размер определяется размерностью модели: файл iqbot.<язык>.<размерность>.bin при размерности 100 занимает около 1 ГБ, при 300 — около 3 ГБ, и памяти сервер занимает примерно столько же, сколько весят файлы загруженных языков, плюс запас на запросы. Сервер с русским и английским языками размерности 100 занимал 1,3 ГБ в покое.
| Размерность | Файл векторов на язык | Память на язык, для расчёта |
|---|---|---|
| 100 | около 1 ГБ | 1,3 ГБ |
| 300 | около 3 ГБ | 4 ГБ |
Нехватка памяти проявляется не сразу: системе приходится останавливать языковой сервер, а сервер NLU продолжает отвечать. Обучение при этом заканчивается ошибкой. Следите за компонентом lang в /health и /status и за плашкой «Языки» в консоли, а память узла планируйте с запасом: языковой сервер, сервер NLU, ядро и PostgreSQL вместе не должны подходить к границе доступной памяти. На Docker Desktop и Colima проверьте, сколько памяти отдано виртуальной машине, а не только хосту.
Если вам поставят модели другой размерности, пересчитайте память узлов или вынесите языковой сервер на отдельный сервер (адрес задаётся в IQB_MODULE_NLU_LANGUAGESOURCES). Размерность задаётся ключом --dim при запуске сервера и должна совпадать с именем файла.
Пропускная способность узла
Ядро платформы обрабатывает диалоги в одном потоке, поэтому один узел под нагрузкой занимает одно ядро процессора. Дополнительные ядра одному узлу производительность не добавляют, добавляют узлы.
Измерение проведено на стенде по методике нагрузочного тестирования. Нагрузка: клиенты ведут диалог банковского бота из трёх сообщений (приветствие, выбор пункта меню, ввод четырёх цифр карты с выполнением действия), каждый клиент ждёт ответ перед следующим сообщением. Сообщением считается один запрос клиента и ответ бота.
| Одновременно ждущих клиентов | Сообщений в секунду, один узел | Задержка ответа, медиана | Задержка ответа, 95 % |
|---|---|---|---|
| 1 | 7 | 0,14 с | 0,16 с |
| 10 | 55 | 0,18 с | 0,23 с |
| 30 | 87 | 0,34 с | 0,57 с |
| 60 | 79–95 | 0,6–0,8 с | 1,0–1,1 с |
Что важно знать при планировании.
- Задержка ответа не бывает меньше 0,14 с даже на пустом узле: после ответа бота платформа ждёт ещё 100 мс (
converse.bufferDelayMs) на случай запоздавших реплик. Поэтому один клиент даёт около 7 сообщений в секунду, а пропускная способность узла набирается числом одновременных клиентов. - Узел ограничивает число одновременно обрабатываемых сообщений (
IQB_CONVERSE_MAX_IN_FLIGHT, по умолчанию 100). Сверх лимита запрос сразу получает503с заголовкомRetry-After, узел продолжает обрабатывать принятые сообщения с той же скоростью. На стенде при 120 одновременных клиентах узел обработал 58 сообщений в секунду и отклонил лишние. - Для расчёта берите 50 сообщений в секунду на узел: это примерно две трети от измеренных 79–95 при 30–60 одновременных клиентах и оставляет запас на действия бота, которые обращаются к внешним системам и держат слот дольше.
- Несколько узлов делят нагрузку: два узла на стенде обработали 120 сообщений в секунду при 60 клиентах. На отдельных серверах рост ближе к линейному.
- PostgreSQL при 95 сообщениях в секунду занимала около 20 % одного ядра, при 120 — около 20 % на два узла, то есть база данных не была узким местом.
Тестовый сервер
Конфигурация для стенда, разработки, обучения сотрудников и пилотного проекта: все компоненты на одном сервере, один язык. Для работы сценаристов и проверки бота тестовыми пользователями её достаточно. Для продуктива используйте расчёт из следующего раздела.
| Процессор | 4 физических ядра |
| Оперативная память | 8 ГБ |
| Диск | 20 ГБ и больше, плюс место под базу данных |
Если языковому серверу не хватает памяти, система останавливает его, в консоли это выглядит как сообщение Killed. Каждый дополнительный язык размерности 100 добавляет около 1,3 ГБ памяти и 10–15 секунд к времени запуска языкового сервера; при размерности 300 — около 4 ГБ.
Программное обеспечение
- Операционная система. Linux x64 с glibc 2.28 или новее. Docker-образы собраны на Debian 12.
- PostgreSQL версии 13 или новее. Отдельная база, не входит в поставку.
- Docker (по желанию), если установка идёт из образов. См. Установка iQBot в Docker.
- Исходящий доступ в интернет для работы платформы не требуется: языковой сервер работает автономно (
--offline), данные клиентов не покидают контур.
Продуктивные конфигурации
Продуктивная установка собирается из узлов iQBot и общих служб. Что считать узлом и что выносить на отдельные серверы, описано в разделе Размещение компонентов ниже: по умолчанию узел — это ядро, Studio, NLU, Messaging и языковой сервер вместе, а общие для всех узлов только база данных и, в кластере, Redis.
Узлы ядра. Рассчитайте число узлов по пиковой нагрузке в сообщениях клиентов в секунду. Один узел рассчитывайте на 50 сообщений в секунду (измерено 78–95 на стенде, запас на действия бота и на оборудование). Число рабочих узлов равно пиковой нагрузке, делённой на 50 и округлённой вверх. К ним добавьте один узел запаса на отказ.
| Пик нагрузки, сообщений в секунду | Рабочих узлов | С запасом на отказ |
|---|---|---|
| до 50 | 1 | 2 |
| до 100 | 2 | 3 |
| до 200 | 4 | 5 |
| до 400 | 8 | 9 |
Каждому узлу выделите 4 ядра и 8 ГБ оперативной памяти, если на нём работают свои NLU, Messaging и языковой сервер (один язык размерности 100), и 2 ядра и 4 ГБ, если они вынесены на отдельные серверы. Схемы установки нескольких узлов описаны в разделе Установка в режиме кластера.
База данных. По результатам измерений PostgreSQL расходует около 20 % одного ядра при 95–120 сообщениях в секунду, поэтому для расчёта важнее диск. Одно сообщение клиента вместе с ответами бота занимает в базе около 5 КБ (события и история диалога вместе с индексами): при 10 миллионах сообщений в месяц это около 50 ГБ в месяц, срок хранения задают настройки журналов. Под продуктив выделяйте отдельный сервер с репликой.
NLU и языковой сервер на отдельных серверах. Нужны только в вариантах размещения, описанных ниже. Для сервера NLU рассчитывайте 4 ядра и 8 ГБ, плюс память языкового сервера по таблице выше.
Размещение компонентов
iQBot состоит из нескольких процессов, и каждый из них можно запустить на отдельном сервере: ядро подключается к внешнему NLU параметром nluServer в nlu.json, к внешнему Messaging — переменными IQB_MESSAGING_ENDPOINT и IQB_MESSAGING_ADMIN_KEY, к языковому серверу — IQB_MODULE_NLU_LANGUAGESOURCES. Возможность есть, но пользоваться ею нужно не всегда.
По умолчанию всё на одном узле. Ядро само запускает NLU и Messaging рядом с собой, языковой сервер ставят на тот же сервер. Так узел — самодостаточная единица: добавили узел — получили и обработку диалогов, и распознавание, и доставку сообщений для него, без лишнего сетевого шага на каждом сообщении и без отдельной точки отказа. Общими для узлов остаются только база данных (и Redis в кластере). Все замеры и расчёты в этом документе сделаны для такой схемы.
Когда компонент выносят на отдельный сервер:
| Компонент | Оставить на узле | Вынести отдельно |
|---|---|---|
| Языковой сервер | До трёх узлов или один язык размерности 100: 1,3 ГБ на узел терпимо. | От четырёх узлов, несколько языков или модели размерности 300: один общий сервер (или два за виртуальным адресом) экономит по 1,3–4 ГБ на каждом узле. Сервер не хранит состояния, его можно перезапускать и резервировать независимо. Адрес задаётся в IQB_MODULE_NLU_LANGUAGESOURCES на всех узлах. |
| NLU | Обычная нагрузка: распознавание идёт локально, обучение редкое. | Обучение больших ботов или частое обучение мешает диалогам на узле (обучение занимает до трёх процессов и 2 ГБ). Выделенный сервер NLU разгружает узлы; за ним нужен собственный балансировщик или виртуальный адрес, иначе он становится единой точкой отказа. Настройка: nluServer: {"autoStart": false, "endpoint": "http://nlu.example.com:3200"} в nlu.json. |
| Messaging | Всегда, если каналы связи идут через iQChannels: Messaging тогда обслуживает только внутренний обмен и эмулятор. | Только если веб-чат или другие каналы подключены к платформе напрямую и нужен один адрес входа для них, либо если база iqbot_messaging требует отдельного обслуживания. У внешнего Messaging свои переменные (ADMIN_KEY, DATABASE_URL, ENCRYPTION_KEY) и своя кластеризация через Redis. |
| База данных | Никогда: на узле только для тестового стенда. | Всегда отдельный сервер с репликой. |
| Redis | — | Всегда отдельно от узлов, когда используется распределение нагрузки. |
Выделенные серверы NLU и языкового сервера убирают из узлов их память и процессор, но добавляют сетевой шаг на каждое сообщение (обычно единицы миллисекунд внутри одной площадки).
Как проверить на своём оборудовании
Измерение повторяется по методике, которая хранится в репозитории платформы, в каталогах docs/load-testing и scripts/load-test. Методика описывает топологии, сценарии диалога, метрики и порядок запуска. Основная проверка для проекта: запустить на целевом оборудовании один узел, затем два, дать каждому узлу нагрузку из 30 одновременно ждущих клиентов и сравнить пропускную способность. Если два узла дали не меньше 1,8 пропускной способности одного, оборудование подходит для схемы с распределением нагрузки.
Масштабирование и отказоустойчивость
Нагрузку увеличивают двумя способами: добавляют ресурсы серверу или устанавливают платформу на несколько серверов. Для нескольких серверов есть два варианта, их описывает раздел Установка в режиме кластера:
- Резервный узел: платформа работает на одном узле, второй запускается при отказе первого;
- Распределение нагрузки: диалоги обрабатывают несколько равноправных узлов за балансировщиком, узлы связаны через Redis.
В обоих вариантах база данных PostgreSQL резервируется репликацией. Резервные копии описаны в разделе Резервное копирование и обновление.
Типовые конфигурации
Готовые наборы оборудования под пиковую нагрузку. Расчёт: один узел iQBot на 50 сообщений в секунду плюс один узел запаса на отказ (см. раздел «Продуктивные конфигурации»). Каждый узел iQBot — полная установка: ядро, Studio, консоль, NLU, Messaging и языковой сервер для одного языка с векторами размерности 100; на второй язык добавьте 1,5 ГБ памяти каждому узлу, а для моделей размерности 300 берите узлы с 16 ГБ памяти (плюс 4 ГБ на каждый дополнительный язык). Балансировщик и виртуальные адреса базы данных и Redis обеспечивает инфраструктура заказчика. Диск базы данных указан на хранение диалогов за 30 дней при средней нагрузке в треть от пиковой (около 5 КБ на сообщение); при другом сроке хранения пересчитайте пропорционально.
| 50 сообщений в секунду | 100 сообщений в секунду | 200 сообщений в секунду | 400 сообщений в секунду | |
|---|---|---|---|---|
| Схема | резервный узел: работает один узел, второй запускается при отказе | распределение нагрузки | распределение нагрузки | распределение нагрузки |
| Узлы iQBot | 2 × (4 ядра, 8 ГБ, 40 ГБ) | 3 × (4 ядра, 8 ГБ, 40 ГБ) | 5 × (4 ядра, 8 ГБ, 40 ГБ) | 9 × (4 ядра, 8 ГБ, 40 ГБ) |
| Redis | не нужен | 2 × (1 ядро, 1 ГБ) с Sentinel или виртуальным адресом | 2 × (1 ядро, 1 ГБ) | 2 × (2 ядра, 2 ГБ) |
| PostgreSQL | основной и реплика, 2 × (4 ядра, 8 ГБ) | основной и реплика, 2 × (4 ядра, 8 ГБ) | основной и реплика, 2 × (4 ядра, 16 ГБ) | основной и реплика, 2 × (8 ядер, 32 ГБ) |
| Диск базы данных на 30 дней | 220 ГБ | 440 ГБ | 870 ГБ | 1,7 ТБ |
| Балансировщик | виртуальный адрес (keepalived на узлах) | NGINX, 2 × (2 ядра, 2 ГБ) | NGINX, 2 × (2 ядра, 2 ГБ) | NGINX, 2 × (4 ядра, 4 ГБ) |
| Итого ядер и памяти | 16 ядер, 32 ГБ | 26 ядер, 46 ГБ | 34 ядра, 78 ГБ | 64 ядра, 148 ГБ |
Как читать таблицу.
- Узлы iQBot: 4 ядра на узел, потому что кроме ядра платформы (одно ядро под нагрузкой) на узле работают NLU с обучением моделей, Messaging и языковой сервер. Память: ядро и Studio до 3 ГБ под нагрузкой, NLU 2 ГБ, языковой сервер 1,3 ГБ на язык при размерности 100, Messaging 0,3 ГБ, остальное системе и запасу.
- Число узлов включает запасной: при отказе одного узла остальные принимают его клиентов без потери пропускной способности.
- Redis хранит только служебные данные (задания, инвалидация кэша, комнаты socket.io, блокировки), ему хватает минимальной машины; важна отказоустойчивость, а не ресурсы.
- PostgreSQL на стенде занимала около 20 % одного ядра при 100 сообщениях в секунду; ресурсы базы заложены с запасом на отчёты, обучение NLU и обслуживание, диск — главный ресурс.
- В конфигурациях на 200 и 400 сообщений в секунду языковой сервер выгоднее вынести на два отдельных сервера (по 2 ядра и 4 ГБ на язык размерности 100) и уменьшить память узлов до 6 ГБ, см. раздел «Размещение компонентов».