Справочник системных ошибок и решений

Windows Server, Active Directory, 1С:Предприятие, СУБД, Linux, Cisco, MikroTik, Asterisk.

⚠️ Важная информация Все материалы, инструкции, команды и скрипты на сайте предоставлены исключительно в ознакомительных целях. Их применение может повлиять на работу операционной системы, программного обеспечения, баз данных, сетевого оборудования и других компонентов инфраструктуры. Перед выполнением действий создайте резервную копию и по возможности протестируйте изменения в безопасной среде. Пользователь самостоятельно оценивает риски и несет ответственность за результат. При отсутствии необходимых знаний обратитесь к квалифицированному ИТ-специалисту.

LCR_ROUTING_FAIL IP-Телефония и СКУД

Настройка динамической маршрутизации вызовов (LCR) в диалплане Asterisk

Обновлено: 24.08.2026 · Официальная документация ↗
  • Неэффективные расходы на исходящую связь из-за отправки вызовов через дорогих транзитных операторов.
  • Ошибки дозвона при падении основного SIP-транка (отсутствие резервного переключения).
  • Сложности при маршрутизации международных вызовов по географическим префиксам и кодам мобильных операторов (MNP).

1. Принцип организации LCR (Least Cost Routing)

LCR в Asterisk анализирует префикс вызываемого номера (E.164), статус доступности провайдеров (SIP/PJSIP qualify) и себестоимость минуты разговора, после чего направляет вызов в самый экономичный маршрут с автоматическим переходом на резервные транки (Failover) при отказе.

2. Настройка транков в pjsip.conf

[trunk-provider-a]
type=endpoint
context=from-trunk
disallow=all
allow=alaw
allow=ulaw
aors=trunk-provider-a-aor

[trunk-provider-b]
type=endpoint
context=from-trunk
disallow=all
allow=alaw
allow=ulaw
aors=trunk-provider-b-aor

3. Конфигурация диалплана с отказоустойчивым LCR

Отредактируйте файл /etc/asterisk/extensions.conf:

[outbound-lcr]
; Маршрутизация мобильных номеров (Дешевле через Provider A)
exten => _89XXXXXXXXX,1,NoOp(=== LCR: Mobile Route for ${EXTEN} ===)
 same => n,Set(TARGET_NUM=${EXTEN})
 same => n,Gosub(sub-dial-lcr,s,1(trunk-provider-a,trunk-provider-b,${TARGET_NUM}))

; Маршрутизация городских номеров (Дешевле через Provider B)
exten => _8[348]XXXXXXXX,1,NoOp(=== LCR: PSTN Route for ${EXTEN} ===)
 same => n,Set(TARGET_NUM=${EXTEN})
 same => n,Gosub(sub-dial-lcr,s,1(trunk-provider-b,trunk-provider-a,${TARGET_NUM}))

; Подпрограмма дозвона с Failover
[sub-dial-lcr]
exten => s,1,NoOp(Dialing via Primary: ${ARG1})
 same => n,Dial(PJSIP/${ARG3}@${ARG1},30,T)
 same => n,NoOp(Primary Trunk Status: ${DIALSTATUS} / HangupCause: ${HANGUPCAUSE})
 same => n,GotoIf($["${DIALSTATUS}" = "ANSWER"]?success)
 same => n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy)
 ; Если транк недоступен, звоним через резервный транк ARG2
 same => n,NoOp(Failing over to Secondary: ${ARG2})
 same => n,Dial(PJSIP/${ARG3}@${ARG2},30,T)
 same => n,GotoIf($["${DIALSTATUS}" = "ANSWER"]?success)
 same => n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy)
 same => n,Playtones(congestion)
 same => n,Congestion(10)
 same => n(busy),Playtones(busy)
 same => n,Busy(5)
 same => n(success),Hangup()

4. Интеграция LCR с базами данных через func_odbc

Для динамического извлечения стоимости направлений настройте /etc/asterisk/func_odbc.conf:

[LCR_ROUTE]
dsn=asterisk-db
readsql=SELECT trunk_name FROM lcr_routes WHERE '${ARG1}' LIKE CONCAT(prefix, '%') ORDER BY length(prefix) DESC, cost ASC LIMIT 1

Вызов функции в диалплане:

exten => _X.,1,Set(BEST_TRUNK=${ODBC_LCR_ROUTE(${EXTEN})})
 same => n,Dial(PJSIP/${EXTEN}@${BEST_TRUNK},30)
💡 Практика специалистов: Не используйте сложные SQL-запросы в реальном времени при высокой плотности одновременных звонков (более 100 CPS). Кэшируйте таблицы префиксов LCR в память с помощью AstDB или локального Redis.

Частые вопросы (FAQ)

Как отличить реальную занятость абонента (BUSY) от сбоя сети у оператора (CHANUNAVAIL)?

Переменная ${DIALSTATUS} принимает значения CHANUNAVAIL, CONGESTION, BUSY, NOANSWER. В подпрограмме LCR переключение на резервный транк должно происходить только при CHANUNAVAIL и CONGESTION, чтобы не беспокоить занятого клиента повторным дозвоном.

Как LCR обрабатывает перенесенные мобильные номера (MNP)?

Для точного учета MNP перед маршрутизацией выполняется HTTP/REST или SQL-запрос к локальной/внешней базе перенесенных номеров для определения фактического префикса оператора (Routing Number/RN).

Можно ли балансировать трафик между одинаковыми транками по весам?

Да, с помощью функции RAND() в диалплане (например, GotoIf($[${RAND(1,100)} <= 70]?routeA:routeB)) или через модуль распределения очередей и групп каналов.

Как избежать зацикливания звонка при отказе всех провайдеров?

Всегда ограничивайте глубину переходов жестким списком аргументов в подпрограмме Gosub и завершайте обработку отправкой приложения Congestion() или Hangup().

Полезные материалы
Рекомендуем