Будет много текста, да еще и без картинок. Заранее благодарен тем, кто дочитает статью до конца. Постараюсь как минимум не быть нудным :-)
Раздел для тех, кто не в теме.
Кто уже читал мои предыдущие статьи и знает про AMI (Asterisk Manager Interface) и AJAM, может смело пропустить этот раздел.
AMI – это интерфейс управления Asterisk-ом. Но, подключения к AMI, как и девушки, бывают разные. Два основных:
- AMI поверх TCP, который часто называют просто AMI
- AMI поверх HTTP, его еще называют AJAM (Asynchronous Javascript Asterisk Manager). Хотя, особой асинхронности я там не увидел.
Если объяснять на пальцах, то разница между 1 и 2, как между толстым и веб-клиентом. Ссылка для тех, кто-то хочет накуриться правильных английских мануалов.
Внешняя компонента ROM-Asterisk может использовать оба способа подключения.
Внешняя компонента от МИКО использует только AJAM.
Но нам, они пока не нужны – мы будем подключаться без них.
Настройка AJAM на стороне Asterisk
Ребята из МИКО написали хорошую статью о том, как выполнить настройку AJAM в Asterisk. Вдаваться в детали настройки мы не будем, это больше для админа, дайте ему ссылку, пусть настраивает.
Кодировщики AJAM
Что еще нам нужно знать про AJAM? В нем есть разные типы кодировщиков ответов:
- rawman – самый простой, которым мы и будем пользоваться
- arawman – тоже самое, что и rawman, плюс использование более навороченной HTTP-digest аутентификации с MD5-хешами
- mxml – ответы сервера кодируются в XML
- manager – кодирует ответы в простые HTML-формы. Этот кодировщик годится разве что на побаловаться вначале
Схема работы с AJAM
Те, кто уже работал с HTTP-сервером, этот раздел могут пропустить.
Важно понимать, что мы работаем с HTTP-сервером. Понятно, что сразу после получения нами HTTP-ответа, сервер разорвет соединение.
Схема будет такой: Connect -> Запрос -> Ответ -> Disconnect
Если хочется еще что-то спросить у Asterisk-а, тогда добро пожаловать в новую итерацию. Это вам не AMI поверх TCP, когда можно 1 раз «зацепиться» за сервер и просто слушать события.
Алгоритм наших действий
Не менее важно понимать сам алгоритм наших действий. По шагам:
- Устанавливаем HTTP-соединение
- Авторизуемся. При удачной авторизации, сервер вернет нам Cookie, который мы прихраним для использования в следующем HTTP-запросе
- Выполняем нужный нам HTTP-запрос, обновляем Cookie.
Реализация
Считаем, что админ уже все настроил и можно приступать.
Все, что нам нужно – это HTTPСоединение и ровные руки, чтобы отправлять ровные запросы.
Код работы с Asterisk настолько тривиальный, что его нет смысла здесь приводить. Все сводится к элементарной отправке и чтению HTTP-запросов. Не верите? Смотрите сами:
Организация соединения:
Соединение=Новый HTTPСоединение(IP,Port,,,,Таймаут,);
Отправка и чтение запроса:
ТекстКоманды="/asterisk/rawman?action=…бла-бла-бла";
Запрос=Новый HTTPЗапрос();
Запрос.АдресРесурса=ТекстКоманды;
Ответ=Соединение.Получить(Запрос);
Это все :)
Ложка дегтя
Когда мы сами являемся источником события, то все вроде бы как хорошо. А вот, когда мы являемся потребителями и хотим просто слушать, то не все так гладко.
Перефразируя мем «нельзя просто так взять и получать события по AJAM». При работе через AJAM нам нужно будет периодически задалбывать HTTP-сервер запросами типа «Сервер, там для меня случайно нет событий?».
Допустим, нам нужно получить инфу о том, что на нас идет входящий звонок. Тогда нам нужен какой-то обработчик ожидания, который периодически будет опрашивать HTTP-сервер.
Именно для такого случая, придумали AMI-команду WaitEvent. Она делает следующую вещь - говорит Asterisk-у: «Мол, я тут событие жду. Не разрывай пож-та соединение пока оно не придет. Я готов ждать максимум 30 секунд». Asterisk конечно же так и поступит.
Но, все это время, пока мы ждем событие, наш HTTP-запрос будет находиться в «висячем» состоянии и клиентское окно 1С будет выглядеть зависшим.
- Пользователю, независимо от пола, «висячее» состояние вряд ли понравится
- Сервер тратит свои ресурсы на поддержание открытой сессии
Вы спросите, а может делать частые HTTP-запросы, допустим каждые 10 секунд, с таймаутом ожидания 10 секунд?
Может быть… Я же не знаю вашей нагрузки на Asterisk и на 1С.
ИМХО, здесь важно найти оптимальный баланс - и сервер не задолбать, и не пропустить важное событие AMI.
И что с этим делать?
Думаю, нужно подбирать решение по конкретной ситуации. Обращайтесь – помогу, если смогу.
В качестве абстрактных рекомендаций, могу сказать следующее:
- Ищите, тестируйте и найдете. Весь инструмент во вложенной к статье обработке. Поиграйтесь с частотой запросов и с таймаутом ответа.
- Пофильтруйте события – хотя бы уберите лишние классы событий. Об этом написано в других моих статьях.
Если пользователь использует толстый клиент, то скорее всего, он сидит внутри сети. Тогда нечего заморачиваться, можно использовать обычный AMI через TCP. Подключаем этого пользователя через ROM-Asterisk и пусть себе работает.
Если пользователь использует тонкий клиент и сидит внутри сети, тогда тоже самое – AMI поверх TCP и ROM-Asterisk. Кстати, тонкому клиенту удаленному, но с хорошим каналом, это тоже подойдет.
Если пользователь использует веб-клиент или же тонкий клиент на нестабильном канале, тогда однозначно AJAM.
Небольшой хак
Если у пользователя НЕ веб-клиент, но вы хотите использовать именно AJAM, а не AMI, тогда могу вам дать хорошую подсказку, как уйти от «висячего» HTTP-запроса.
Вместо объекта HTTPСоединение можно использовать соединение ROM-Asterisk, а вместо объекта HTTPЗапрос использовать метод ВыполнитьКоманду. В этом случае, подмерзания не будет – ответ придет асинхронно, как внешнее событие. Вы отдали команду и забыли, когда придет ответ – Asterisk вам сам скажет.
Выложу реализацию этого хозяйства в отдельной статье.
Выводим выводы
Подключаться к AJAM без внешних компонент можно и это совершенно не сложно. Хотя, с точки зрения производительности, это не всегда оптимально. Иногда вместо HTTP-соединения, правильнее использовать соединение по TCP. Может в будущем в 1С появится объект TCPСоединение, а пока для этого нужны внешние компоненты.
Использовать AJAM лучше там, где это действительно нужно. Если можно использовать AMI поверх TCP – используйте, с ним проще. На нем можно делать всякие потрясающие штуки. Зато, AJAM – отличное решение для веб-клиента или плохих каналов.
К статье приложена внешняя обработка AJAM, которая будет работать как в режиме управляемого приложения, так и в обычном режиме.
Успешной вам разработки!