5.8 KiB
Routing
Маршрутизация звонков состоит из двух уровней:
- Routing Rules — priority-based правила с regex-матчингом (first-match-wins)
- Balancing Mode — стратегия выбора ноды внутри правила или глобально
Routing Rules
Правила хранятся в data/routes.json и проверяются в порядке Priority (меньше = раньше). Первое совпавшее правило определяет маршрутизацию. Если правило не сработало (нода мертва / пул пуст) — переход к следующему. Если ни одно правило не совпало — глобальный PickNode().
Match Conditions (AND-логика)
Все непустые поля должны совпасть одновременно. Пустые поля — не проверяются.
| Поле | Тип | Описание |
|---|---|---|
match_caller_id |
regex | Caller ID звонящего |
match_destination |
regex | Номер назначения |
match_ingress_trunk |
regex | ID входящего транка |
match_days |
string | Дни недели: "1-5" (пн-пт), "1,3,5" (пн,ср,пт), "6" (сб). Воскресенье = 0 или 7 |
match_time_start |
"HH:MM" |
Начало временного диапазона |
match_time_end |
"HH:MM" |
Конец временного диапазона |
Action Types
| Тип | Поле | Описание |
|---|---|---|
node |
action_node_id |
Маршрутизация на конкретную ноду. Если нода dead/stale/lethal — fallthrough к следующему правилу |
pool |
action_pool_ids |
Выбор лучшей ноды из заданного списка (по текущему режиму балансировки). Пустой/нездоровый пул — fallthrough |
auto |
— | Fallthrough к глобальному PickNode() с учётом режима балансировки |
Пример правила
{
"id": "rule-001",
"name": "VIP caller to dedicated pool",
"enabled": true,
"priority": 10,
"match_caller_id": "^7495",
"match_destination": "",
"match_ingress_trunk": "",
"match_days": "1-5",
"match_time_start": "09:00",
"match_time_end": "18:00",
"action_type": "pool",
"action_pool_ids": ["pbx-01", "pbx-02"],
"description": "VIP номера 7495 в бизнес-часы на выделенные ноды"
}
Balancing Modes
Режим балансировки определяет, как выбирается нода из множества healthy-нод (после отсева lethal). Применяется как в глобальном PickNode(), так и внутри pool-правил.
best
Выбирает ноду с максимальным score из кэша. O(1) — bestScore предрассчитывается при каждой метрике.
- Всегда одна и та же нода при одинаковых метриках — максимально нагружает лучшую ноду
- Хорошо для тестирования и сценариев где нужна предсказуемость
weighted_random (по умолчанию)
Выбирает ноду пропорционально score: чем выше score, тем выше вероятность быть выбранной. O(n) — сканирует все ноды.
Алгоритм:
- Отсеивает disabled, stale, lethal (score < 0)
- Суммирует score всех кандидатов (
totalScore) pick = rand(0, totalScore), идёт по кандидатам, вычитая score- Если
totalScore <= 0— равновероятный выбор
- Распределяет нагрузку пропорционально готовности
- Предсказуемость ниже, но утилизация выше — менее загруженные ноды получают пропорционально меньше звонков
Переключение режима
Через API:
PUT /api/route/mode
Authorization: Bearer <admin-jwt>
{"mode": "best"}
Через конфиг:
{ "balance_mode": "weighted_random" }
Допустимые значения: "best", "weighted_random". API-эндпоинт сразу применяет режим и сохраняет в config.json.
Routing Rules API
Правила маршрутизации CRUD — /api/routing/rules*. Все эндпоинты требуют JWT (admin).
| Метод | Путь | Описание |
|---|---|---|
GET |
/api/routing/rules |
Список всех правил (с hits) |
POST |
/api/routing/rules |
Создать новое правило |
PUT |
/api/routing/rules/{id} |
Обновить правило (частично) |
DELETE |
/api/routing/rules/{id} |
Удалить правило |
PUT |
/api/routing/rules/{id}/toggle |
Вкл/выкл: {"enabled":true} |
PUT |
/api/routing/rules/reorder |
Новый порядок: ["rr-abc", "rr-def"] — переназначает Priority |
Правила хранятся в data/routes.json и применяются в порядке Priority (first-match-wins).
Ответ /api/route
В ответе маршрутизации появилось поле matched_rule — имя сработавшего правила (или "none" если правило не применилось):
{
"node_id": "pbx-03",
"score": 88,
"sip_gateway": "sip:pbx03.lan:5060",
"matched_rule": "VIP to dedicated"
}