Настройка балансировки транков FreePBX

Оболочка FreePBX обладает многими преимуществами, однако в то же время и некоторыми, как мы считаем, недоработками. В числе прочих пользователи часто сталкиваются с проблемой объединения транков в группы при исходящей маршрутизации. Особо это проявляется при организации взаимодействия связки Asterisk c GSM шлюзами, в частности с популярными нынче GoIP. 

voip gsm shlyuz goip1

 

При организации внешнего маршрута транки объединяются в группу и занимаются последовательно, начиная с первого канала. Это приводит к дисбалансу нагрузки, когда первый транк занимается чаще всего, а  последний никогда (разумается, в зависимости от трафика). Обычно в GSM шлюзах используются сим-карты с тарифами, включающие пакеты минут, и вопрос равномерного распределения исходящего трафика стоит достаточно остро.

Штатных средств для изменния порядка очередности занятия транков в маршруте у FreePBX в отличие от оборудования традиционной телефонии , где эта функция имеется практически у любого оборудования, не заложено, поэтому было найдено решение с использованием диалпланов Asterisk. Нужно отметить, что различных способов решения задачи балансировки на разных ресурсах в сети интернет множество. Однако все они достаточно громоздки и сложны. Представленный способ очень прост и эффективен.

После создания транков между Astrisk и GoIP  в оболочке FreePBX необходимо зайти в файл extensions_additional.conf и скопировать оттуда кусок диалплана с соответствующим маршрутом, в нашем случае outrt-1:

[outrt-1] ; goip-32
include => outrt-1-custom
exten => _8[3489]XXXXXXXXX,1,Macro(user-callerid,LIMIT,EXTERNAL,)
exten => _8[3489]XXXXXXXXX,n,Gosub(sub-record-check,s,1(out,${EXTEN},no))
exten => _8[3489]XXXXXXXXX,n,Set(_ROUTEID=1)
exten => _8[3489]XXXXXXXXX,n,Set(_ROUTENAME=goip-32)
exten => _8[3489]XXXXXXXXX,n,Set(MOHCLASS=${IF($["${MOHCLASS}"=""]?default:${MOHCLASS})})
exten => _8[3489]XXXXXXXXX,n,Set(_CALLERIDNAMEINTERNAL=${CALLERID(name)})
exten => _8[3489]XXXXXXXXX,n,Set(_CALLERIDNUMINTERNAL=${CALLERID(num)})
exten => _8[3489]XXXXXXXXX,n,Set(_EMAILNOTIFICATION=FALSE)
exten => _8[3489]XXXXXXXXX,n,Set(_NODEST=)
exten => _8[3489]XXXXXXXXX,n,Macro(dialout-trunk,1,${EXTEN},,off)
exten => _8[3489]XXXXXXXXX,n,Macro(dialout-trunk,2,${EXTEN},,off)
exten => _8[3489]XXXXXXXXX,n,Macro(dialout-trunk,3,${EXTEN},,off)
exten => _8[3489]XXXXXXXXX,n,Macro(outisbusy,)

;--== end of [outrt-1] ==--;

Строки с записями dialout-trunk описывают количество  внешних транков (в нашем примере их 3). Далее вставляем его в файл extensions_override_freepbx.conf изменив строки, как представлено ниже:

[outrt-1] ; goip-32
include => outrt-1-custom
exten => _8[3489]XXXXXXXXX,1,Macro(user-callerid,LIMIT,EXTERNAL,)
exten => _8[3489]XXXXXXXXX,n,Gosub(sub-record-check,s,1(out,${EXTEN},no))
exten => _8[3489]XXXXXXXXX,n,Set(_ROUTEID=1)
exten => _8[3489]XXXXXXXXX,n,Set(_ROUTENAME=goip-32)
exten => _8[3489]XXXXXXXXX,n,Set(MOHCLASS=${IF($["${MOHCLASS}"=""]?default:${MOHCLASS})})
exten => _8[3489]XXXXXXXXX,n,Set(_CALLERIDNAMEINTERNAL=${CALLERID(name)})
exten => _8[3489]XXXXXXXXX,n,Set(_CALLERIDNUMINTERNAL=${CALLERID(num)})
exten => _8[3489]XXXXXXXXX,n,Set(_EMAILNOTIFICATION=FALSE)
exten => _8[3489]XXXXXXXXX,n,Set(_NODEST=)

exten => _8[3489]XXXXXXXXX,n,Set(randomtrunk=${RAND(1,3)});
exten => _8[3489]XXXXXXXXX,n,execif($["${randomtrunk}"="1"]?Macro(dialout-trunk,1,${EXTEN},,off)
exten => _8[3489]XXXXXXXXX,n,execif($["${randomtrunk}"="2"]?Macro(dialout-trunk,2,${EXTEN},,off)
exten => _8[3489]XXXXXXXXX,n,execif($["${randomtrunk}"="3"]?Macro(dialout-trunk,3,${EXTEN},,off)
exten => _8[3489]XXXXXXXXX,n,Macro(outisbusy,)

Переменная randomtrunk случайным образом определяет, какой канал занимать в диапазоне от 1 до 3, чем обеспечивается равномерное занятие каналов. Следует учитывать, что при внесениии изменений в исходящий маршрут через оболочку FreePBX необходимо снова проделать описанную выше процедуру.

У вышеописанного способа балансировки есть существенный недостаток. В случае занятости выбранной линии набирающий внутренний абонент уйдёт в отбой. Чтобы решить указанный недостаток, доработаем контекст следующим образом: 

[outrt-1] ; goip-32
include => outrt-1-custom
exten => _8[3489]XXXXXXXXX,1,Macro(user-callerid,LIMIT,EXTERNAL,)
same => ,n,Gosub(sub-record-check,s,1(out,${EXTEN},no))
same => ,n,Set(_ROUTEID=1)
same => ,n,Set(_ROUTENAME=goip-32)
same => ,n,Set(MOHCLASS=${IF($["${MOHCLASS}"=""]?default:${MOHCLASS})})
same => ,n,Set(_CALLERIDNAMEINTERNAL=${CALLERID(name)})
same => ,n,Set(_CALLERIDNUMINTERNAL=${CALLERID(num)})
same => ,n,Set(_EMAILNOTIFICATION=FALSE)
same => ,n,Set(_NODEST=)

same => ,n,Set(randomtrunk=${RAND(1,3)});
same => ,n,Macro(dialout-trunk,${randomtrunk},${EXTEN},,off)
same => ,n,Set(randomtrunk=${RAND(1,3)});
same => ,n,Macro(dialout-trunk,${randomtrunk},${EXTEN},,off)
same => ,n,Set(randomtrunk=${RAND(1,3)});
same => ,n,Macro(dialout-trunk,${randomtrunk},${EXTEN},,off)
same => ,n,Macro(outisbusy,)

Попытки выбрать свободный транк осущствляются в этом примере 3 раза. В случае необходимости ничего не мешает увеличить количество попыток "бросить кубик" большее количество раз простым копированием  строк )))