Pull to refresh

TalkPad изнутри

Reading time4 min
Views4.3K


Прошел почти год после публикации первой вводной статьи о TalkPad. В процессе эксплуатации и развития сервиса мы столкнулись со многими технологическими проблемами, часть из которых успешно преодолели. Сегодня мы хотим рассказать вам о том, как устроена серверная сторона TalkPad.

Напомню что TalkPad — это сервис, который предоставляет возможность позвонить на городские и мобильные телефоны прямо из браузера, установив плагин.

Итак, как же все-таки может быть устроен бэкенд высоконагруженного сервиса телефонии?

TalkPad построен на нескольких протоколах передачи данных. Мы используем SIP (Session Initiation Protocol) и SDP (Session Description Protocol) для установления сессии между пользователями и передачи метаданных, а для передачи непосредственно голосовых данных используется RTP (Real-Time Transport Protocol). Есть и другие протоколы для задачи установления соединения (Jingle, H.323, …), но SIP в настоящее время наиболее популярен.

1. Определение местоположения пользователей
В проекте мы используем высокопроизводительный программный SIP-коммутатор OpenSIPS, который помимо прочего обсуживает базу регистраций.

Для того, чтобы сервер знал, куда именно отправлять входящие звонки, каждый клиент отправляет серверу SIP-сообщение REGISTER, в котором сообщает свой сетевой адрес и порт. Чтобы пользователь не смог принять чужие звонки в SIP-регистрации необходима аутентификация и авторизация.

База регистраций обслуживается в памяти каждого сервера OpenSIPS с периодическим сбрасыванием (по таймеру) состояния в локальный PostgreSQL (о том как синхронизируются данные в памяти чуть ниже).

2. А если пользователь за NAT-маршрутизатором?
Почти все пользователи находятся за домашними/офисными/публичными роутерами (NAT-маршрутизаторами). В этом случае клиент не знает свой внешний сетевой адрес. Для решения этой проблемы существует протокол STUN (Session Traversal Utilities for NAT). STUN-клиент пользователя просто посылает запрос STUN-серверу (один из модулей OpenSIPS), а сервер отвечает ему информацией с какого сетевого адреса пришел пакет. Комбинируя различные STUN тесты пользователь может определить свой тип NAT.

Тип NAT, который мы определили, записывается в SIP-сообщения REGISTER и INVITE. В общем случае голосовой трафик идет между клиентами напрямую в режиме P2P. Однако, в случае, если тип NAT одного из пользователей был определен как симметричный, мы не можем этого сделать. Для этого OpenSIPS переписывает SIP сообщения таким образом, чтобы трафик между пользователями направился через RTPProxy-сервер (модуль OpenSIPS). По статистике TalkPad голосовой трафик через сервер проходит примерно для 28-30% пользователей.

3. SBC & Биллинг
Для того, чтобы пользователи TalkPad могли общаться не только между собой, но и звонить на городские и сотовые телефоны, мы сотрудничаем с операторами местной телефонной связи, общение с которыми происходит так же по протоколам SIP и RTP.

Чтобы корректно считать расход денежных средств пользователя, недостаточно просто проксировать SIP-сообщения пользователя оператору, так как в этом случае мы потеряем контроль за ходом звонка. Более подходящим решением является установление новой SIP-сессии с оператором, но таким образом, чтобы RTP трафик все еще направлялся напрямую между пользователем и оператором (или через сервер в случае, если необходимо выполнить перекодирование голоса).

Эти функции выполняет Session Border Controller (или B2BUA). В последних версиях OpenSIPS уже встроен модуль B2BUA. Кроме того, можно использовать B2BUA от Sippy Software. Однако для TalkPad мы остановились на использовании YATE — классической ATC компании Null Team, которая естественно сочетает в себе PBX и SBC функционал.

Одно из преимуществ YATE — это модуль Extmodule, который позволяет легко писать свои расширения на языке Python. В качестве движка для обработки асинхронных событий используется Twisted. Именно таким образом мы написали биллинг для TalkPad, который позволяет контролировать баланс пользователя с секундной точностью, причем даже в случае нескольких одновременных звонков. Это выгодно отличает наш биллинг от решений на базе протокола RADIUS.

4. Failover
TalkPad сочетает DNS-балансировку с CARP-отказоустойчивостью как изображено на картинке.
OpenSIPS может проксировать как в режиме stateless proxy, так и statefull proxy, в зависимости от используемых модулей. В нашем случае это statefull и поэтому нам нужно чтобы SIP-клиент (voip-плагин) общался с одним и темже OpenSIPS на протяжении сессии. Таким образом SIP-клиент должен отрезолвить DNS-запись 1 раз при старте и использовать до конца сессии.

image

Каждый OpenSIPS сервер реплицирует REGISTER на соседний сервер, дописывая себя в заголовок Path. Это нужно для того чтобы другой OpenSIPS знал с какого адреса нужно ответить клиенту в случае необходимости.

Что же произойдет в случае падения OpenSIPS-Server#1?
В этом случае интерфейс CARP1 на Server#2 автоматически перейдет в положение Master, и оба IP-адреса DNS-записи уже будут роутится на Server#2. Нагляднее всего это изображено на картинке:

image

В случае падения одного из YATE серверов модуль loadbalancer в OpenSIPS эту ситуацию распознает и будет использовать только второй сервер, причем упавший будет периодически проверяться на предмет того, не ожил ли он.

Схема когда просто два пользователя отрезолвили два разных IP и говорят через браузер:

image

5. Базы данных
В проекте мы используем PostgreSQL и приложения из open-source комплекта Skytools (от Skype): пулер соединений pgbouncer и менеджер репликации walmanager.

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

Пользуясь случаем, хотим сообщить, что команда TalkPad активно ищет талантливых продавцов, партнеров, которые бы хотели встроить телефонию в свой сервис, и инвесторов.
Tags:
Hubs:
Total votes 42: ↑41 and ↓1+40
Comments29

Articles