Asterisk, ARI. Коммутируй как Бог

В этой небольшой статье ничего не будет про план нумерации астериска. Речь пойдет про ARI — гибкий интерфейс управления Астериском.

Как только в астериск приходит инвайт, и вызов уходит в нашу программу (Stasis) мы получаем возможность для низкоуровневого построения звонка.

Взаимодействие с ARI происходит через прием событий по websocket от астериска, обработку и создания новых событий через HTTP REST API в сторону ARI.

StasisStart

Событие, которое получает наша программа, когда канал вошел в стазис контекст. StasisStart может сигнализировать, например о начале исходящего либо входящего звонка, в результате чего мы запускаем низкоуровневую логику по созданию канала в сторону другого абонента, добавлению его в бридж с каналом инициатором и дозвону.

Упрощенная схема обычного звонка

  1. Получили инвайт (StasisStart) событие от ARI, что сигнализирует о созданном канале A
  2. Создали канал B с эндпоинтом в сторону сип пира, либо в локальный прокси. (пример. SIP/MY_PEER/79001231122)
  3. Канал А из п.1 и B из п.2 объядинили в bridge
  4. Сделали дозвон (dial) в канал B
  5. Подождали ARI событие ChannelStateChange для канала B. И в случае если state — ‘Up’, запускаем ответ в канал A и звонок диалог начинается.
  6. При получении события ChannelHangupRequest для канала A либо B разрушаем звонок.

Сессия звонка

Созданных каналов может быть множество и есть необходимость знать, к каким звонкам относятся события по каким каналам. Поэтому при создании каналов в сторону другого абонента, можно записывать в стор для созданного канала указатель на id канала A, а в сторе для канала A хранить все данные, включая CDR и прочую техническую информацию.

В качестве хранилища я бы рекомендовал использовать redis, так как при больших cps и интенсивных запросах в базу данных может образоваться существенная нагрузка на жесткие диски и просесть производительность.

Оптимизация

Для оптимальной работы вашего ARI приложения под большим cps, я бы рекомендовал свести к минимуму запросы в реляционную базу данных. В своей практике я использовал запросы для небольшой ограничительной логики в момент инициализации звонка и для записи CDR после окончания звонка. Все остальные запросы выполняются в рэдис.

Тест производительности

Для тестирования я использовал консольную утилиту baresip, инициировав баш скриптом 200 дозвонов по пулу тестовых номеров, которые отвечают tt-monkeys.

200 параллельно запущенных звонков сумарно потребили около 5% загрузки на CPU. Все звонки завершились успешно, включая записанные CDR.

Дебаг stasis приложения, которое сигнализирует об отвеченных звонках
SIP сигнализация