Яндекс.Метрика

Курс Zabbix: мониторинг Asterisk и VoIP

Курс Zabbix: мониторинг Asterisk и VoIP с 8 сентября по 12 сентября

Количество
свободных мест

8 Записаться

Дистанционные курсы по Asterisk

Дистанционные курсы по Asterisk с 18 августа по 24 августа

Количество
свободных мест

2 Записаться

Курсы по Mikrotik MTCRE

Курсы по Mikrotik MTCRE с 8 декабря по 11 декабря

Количество
свободных мест

6 Записаться
Стреляем в ногу: наш опыт замедления kamailio
14
Мастер-класс
Игорь Гончаровский
Стреляем в ногу: наш опыт замедления kamailio
скачать презентацию

Стреляем в ногу: наш опыт замедления kamailio

Это скорее лирическая импровизация, основанная на реальных событиях. История о ситуации, которая в определённый момент добавила немало нервозности и ввела в замешательство, но в итоге привела к полезным выводам.

Архитектура и исходные условия

Рассматриваемая система построена из следующих компонентов:

  • Kamailio — маршрутизатор SIP-сообщений.
  • RTP Engine — обработка и проброс медиапотока.
  • RTP Engine Recording — запись медиапотока.
  • Redis — передача событий между компонентами.

Приложение, работающее в связке с этой системой, в реальном времени обрабатывает PCM-аудио. Для получения аудио Kamailio отправляет команду в RTP Engine на начало передачи медиапотока. При этом Kamailio через Redis передаёт данные о звонке (начало и завершение) в приложение. Логика проста: два события — INVITE и BYE, публикуемые в Redis, и команда RTP Engine Start Forwarding.

Первоначальные тесты показали, что система выдерживает 100–150 CPS (calls per second). На этой отметке разработка продолжилась. Однако при внедрении у заказчика проявилось резкое ограничение — на нагрузке около 30 CPS начинались проблемы: повторные INVITE, потеря BYE, при этом сбои происходили внутри Kamailio, а общая загрузка системы оставалась низкой (load average ~0.5).

Первое расследование

Первое предположение — проблемы в RTP Engine. Его отключение действительно снимало сбои в Kamailio. Логи подтверждали: при возникновении проблем Kamailio не мог связаться с RTP Engine. Однако дальнейшее исследование показало, что RTP Engine работал корректно, за исключением отсутствия настройки параметра FinalTimeout. Это могло приводить к «зависанию» портов при перезапуске Kamailio, но в данном случае влияние было исключено.

Следующий кандидат — RTP Engine Recording. Предполагалось, что запись медиа может блокировать RTP Engine из-за высокой нагрузки на диск. Однако архитектура записи устроена так, что RTP Engine и модуль записи разделяют каталог для обмена метаданными, и запись не блокирует RTP Engine — обмен идёт через inotify, а звуковой поток читается асинхронно. Тесты с медленным диском не воспроизвели проблему.

Поиск глубже

Далее исследование ушло в настройки ядра Linux — были опробованы наборы «оптимизаций» для UDP highload. Это оказалось бесполезным и даже потенциально опасным из-за изменения распределения портов.

Возникла гипотеза о проблемах в прикладной части. При тестах с отключённой публикацией событий в Redis система работала без сбоев, но терялась информация о звонках. Увеличение числа SIP-процессов Kamailio (children) с 8 до 512 улучшало ситуацию, но не решало проблему.

Истинная причина

Расследование показало, что после обновления библиотеки работы с Redis изменился пул соединений. Каждое медиаприложение держало собственное соединение с Redis. Количество подключений выросло с 64 до 640. Поскольку публикация (PUBLISH) в Redis отправляется на все подписанные клиенты, время публикации увеличилось в 10 раз. Это приводило к тому, что данные о звонке публиковались медленнее, чем таймер повторной отправки INVITE. При этом повторные INVITE повторно публиковались, что ещё сильнее нагружало Kamailio.

Ключевой момент: публикация в Redis в Kamailio — синхронная операция, блокирующая обработку SIP-пакета. Рост времени публикации блокировал все процессы Kamailio, что и приводило к обвалу.

Решение

В новой архитектуре медиатрафик обрабатывался акторной моделью в одном процессе, который держал одно соединение с Redis. Механизм публикации был изменён:

  • PUBLISH заменён на схему с проверкой наличия подписчиков.
  • Если подписчиков нет, данные записываются в Redis по ключу с TTL (времени жизни) и позже забираются обработчиком при поступлении соответствующего события.
  • Таким образом, публикация идёт только в одного потребителя, что устраняет экспоненциальный рост времени отправки.

Альтернативой могло бы быть использование асинхронных HTTP-запросов или модулей присутствия в Kamailio/OpenSIPS, но в рамках текущей реализации Redis оказался быстрее адаптирован к новым требованиям.

Заключение

  1. В системах VoIP необходимо учитывать, что звонок — это не только начало и конец, но и повторные передачи (ретрансмитты).
  2. Следует тщательно тестировать производительность не только на уровне нагрузки, но и по времени выполнения конкретных операций — например, публикации в Redis.
  3. Любые операции с внешними системами в Kamailio должны выполняться асинхронно или с контролем времени, чтобы не блокировать SIP-процессы.
  4. При изменении библиотек и инфраструктурных компонентов нужно учитывать влияние на производительность в боевых условиях.
  5. Архитектура обмена событиями должна исключать множественные блокирующие публикации в условиях высокой нагрузки.

Проблема оказалась скрытой: внешне система не была перегружена, но из-за синхронного вызова и роста числа подписчиков возникал каскадный сбой. После архитектурных изменений система вернулась к стабильной работе и сохранила запас по нагрузке.

Ежегодная конференция по Asterisk 2025!

Билеты уже в продаже!

Остались вопросы?

Я - Компаниец Никита, менеджер компании Voxlink. Хотите уточнить детали или готовы оставить заявку? Укажите номер телефона, я перезвоню в течение 3-х секунд.

Наши
клиенты

Посмотреть все