Построение отказоустойчивого SIP-прокси/PBX на базе FreeSWITCH mod_sofia (recover)

в 14:42, , рубрики: freeswitch, high availability, ip-телефония, pbx, voip, метки: , , ,

Здравствуйте, уважаемые читатели.

Вот уже несколько месяцев ковыряюсь в прекрасном продукте FreeSWITCH. Он не перестает меня удивлять функциональностью, надежностью и производительностью (даже в тех областях, в которых от него этого не ждешь).

Один из моих экспериментов, который в скором времени, скорей всего, перейдет в продакшн касался изумительной, с моей точки зрения, функции mod_sofia recover. Функция recover позволяет FreeSWITCH (FS) восстановить вызовы после краша или же, если FS работает в высоко доступном кластере подхватить вызовы на второй ноде! ВНИМАНИЕ! без обрывов вызовов абонентов, как в случае проксировании RTP, так и без него.

Реализуется это достаточно просто, благодаря использованию внешней СУБД и настройкам mod_sofia, отвечающего за SIP стэк. Т.е. mod_sofia хранит всю информацию о текущих вызовах во внешней БД, и при краше у второй ноды кластера есть возможность эти настройки прочесть и подхватить вызовы.

Итак, нам понадобятся:

  • FreeSwitch
  • Установленная отдельно СУБД (в моем случае mysql)
  • unixODBC
  • депенденсы, которые потребует FS (описано на вики)
  • heartbeat

Я не буду подробно останавливаться на процессе установки FS и выпиливании из него ненужных модулей, все эксперементы будут ставиться на конфигурации по умолчанию. В конце только добавим какой-нибудь гейтвей, для осуществления внешних звонков.

Будем считать, что все что нам нужно установлено, приступим к самому интересному! Ковырянию конфигов.
Установка FS по умолчанию уже вполне звонибельна и для тестов нам ее будет более чем достаточно.

На сервере БД выполняем:

#mysqladmin -u dba_user -p create fs_cnf

Это создаст БД, в которой FS будет хранить свои настройки.

Наш клайстер будет состоять из 2х рабочих нод и сервера базы данных.

Адрес первой ноды 172.16.100.200
Адрес второй ноды 172.16.100.201
Общий адрес 172.16.100.205
Адрес ДБ сервера 172.16.100.210

Все действия ниже производятся на обоих нодах FreeSWITCH

В файл /etc/odbc.ini вносим параметры подключения к серверу БД

[fsw-cnf]
Description = MySQL ODBC Database
TraceFIle = stderr                                                                                                                                                        
Driver = MySQL
SERVER = 172.16.100.210
USER = fs-usr
PASSWORD = super_secure_password
OPTION = 67108864
DATABASE = fs_cnf

Мы хотим, чтобы FS работал на общем IP, для этого файл freeswitch_base_dir/conf/vars.xml
нужно внести строку:

<X-PRE-PROCESS cmd="set" data="local_ip_v4=172.16.100.205"/>

Для того, чтобы работал recover нужно включить трекинг звонков в sip профилях. Что такое профили прекрасно описано тут. Идем в freeswitch_base_dir/conf/sip_profiles/ и добавляем в настройки обоих профилей (internal, external) строку:

<param name="track-calls" value="true"/>

Так же в обоих профилях указываем параметры подключения к серверу БД

<param name="odbc-dsn" value="fsw-cnf:fs-usr:super_secure_password"/>

Идем в файл freeswitch_base_dir/conf/autoload_configs/switch.conf.xml и добавляем строку или раскоментируем и правим:

<param name="core-db-dsn" value="fsw-cnf:fs-usr:super_secure_password"/>

Это для core настроек FS.

При старте FS сам создаст нужные для работы таблицы.

Далее настраиваем heartbeat:

vim /etc/ha.d/authkeys

auth 1
1 sha1 mega_super_secure_key

chmod 600 /etc/ha.d/authkeys

vim /etc/ha.d/ha.cf

# Логи
logfacility     local0
# Таимауты
keepalive 100ms
deadtime 2
warntime 1
initdead 120
# как будут между собой общаться ноды
udpport 694
bcast   eth0
# Какие ноды учавствуют в нашем клайстере
node fs1 fs2
# После востановления должны ли возвращаться ресурсы на первую ноду?
auto_failback on

vim /etc/ha.d/haresources (на второй ноде нужно поменять хостнейм (fs1 на fs2))

fs1 IPaddr2::64.34.74.73/255.255.255.192/eth0 freeswitch::fsrecover

freeswitch::fsrecover — раздел init.d скрипта, который нам подымет наши профили, его мы добавим в следующем шаге

В /etc/init.d/freeswitch между restart и reload добавим

 fsrecover)
     $FS_HOME/bin/fs_cli -x "sofia profile internal start"
     $FS_HOME/bin/fs_cli -x "sofia profile external start"
     /bin/sleep 1
     $FS_HOME/bin/fs_cli -x "sofia recover"
     ;; 

Теперь когда одна из нод грохнется вторая подымет общий IP и перезапустит профили FS, после чего выполнит заветную команду и подхватит звонки.

Для проверки исходящего вызова нам нужно отредактировать dialplan и добавить гейтвей.
В моем примере я буду использовать voip.ms c десятизначным номером. Идем в freeswitch_base_dir/conf/sip_profiles/external/ и создаем файл следующего содержания:

<include>
  <gateway name="voipms">
    <param name="username" value="your_username" />
    <param name="password" value="your_password" />
    <param name="proxy" value="montreal|houston|newyork|etc.voip.ms" />
    <param name="realm" value="voip.ms" />
    <param name="register" value="true" />
    <param name="sip_cid_type" value="rpd" /> 
  </gateway>
 </include>

В freeswitch_base_dir/conf/dialplan/default.xml добавляем(поменяйте регулярное выражение и параметры caller-id)

<extension name="Outbound 10 Digits">
  <condition field="destination_number" expression="^(d{10})$">
    <action application="set" data="effective_caller_id_number=8001231234"/>
    <action application="set" data="effective_caller_id_name=800 Number"/>
    <action application="bridge" data="sofia/gateway/voipms/$1"/>
  </condition>
</extension>

Запускаем демоны:

chkconfig heartbeat on
service heartbeat start
chkconfig freeswitch on
service freeswitch start

Стартап скрипт фрисвитча его запустит на обоих нодах, но на неактивной ноде не подымутся профили, т.к. нет IP, на котором они запускаются.
Для тестов берем любой экстеншон из freeswitch_base_dir/conf/directory/default, регистрируемся:

Proxy: 172.16.100.205
username: 1000
password: 1234 (Это default_password, его обязательно надо менять в vars.xml)

Набираем любой номер, в процессе разговора кладем одну из нод и вуаля! Heartbeat обнаруживает, что вторая нода лежит, подхватывает общий IP, запускает скрипт, запуская тем самым неактивные профили. Прерывание медиа потока всего 2-3 секунды, т.е. время, которое уходит у хартбита на перехват ресурсов + 1 секунда в freeswitch:fsrecover

Все. Спасибо за внимание, надеюсь статья кому-то пригодится. Пожелания и предложения более чем приветствуются. В планах есть написать про связку mod_xml_curl, mod_lcr и еще кое что.

П.С. Как принято говорить: ”сильно не пинайте, первая статья”.

Литература:
wiki.freeswitch.org

Автор: Sp1tF1r3

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js