Asterisk ARI: Ошибка ari_websockets.c websocket read error: success
Архитектура ARI и природа WebSocket ошибок
Asterisk REST Interface (ARI) использует асинхронные двунаправленные WebSocket-соединения для передачи событий (Event App) вашему внешнему приложению (Node.js, Python, Golang). Ошибка ari_websockets.c: websocket read error: success (или EOF) в логах Asterisk — это парадоксальное сообщение, означающее, что TCP-соединение было закрыто на уровне сети или операционной системы штатно (поэтому "success"), но Asterisk этого не ожидал (поэтому "error"). Бизнес-риски: внешнее приложение перестает получать события о звонках, зависание каналов (Stasis), молчание в трубке у клиентов.
Типовые причины разрыва WS-соединения
| Где рвется | Причина обрыва соединения | Как диагностировать |
|---|---|---|
| Reverse Proxy (Nginx) | Тайм-аут бездействия (proxy_read_timeout). Nginx закрывает простаивающий сокет (обычно через 60 сек). | События рвутся ровно через заданный интервал простоя. |
| Firewall / NAT | UDP/TCP Session Timeout на маршрутизаторе (MikroTik, Cisco). | Обрывы при долгих разговорах без событий. |
| Приложение (App) | Node.js / Python клиент падает по Exception и некорректно закрывает TCP сессию. | Логи самого приложения (PM2, systemd). |
Траблшутинг стабильности ARI WebSockets
Сценарий 1: Настройка тайм-аутов в Nginx (Reverse Proxy)
Если ARI опубликован через Nginx (WSS на порт 443), необходимо увеличить тайм-ауты и явно разрешить апгрейд соединения до WebSocket.
# Конфигурация location для ARI в nginx.conf
location /ari/events {
proxy_pass http://127.0.0.1:8088;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
# Увеличиваем тайм-ауты (в секундах)
proxy_read_timeout 3600;
proxy_send_timeout 3600;
}Сценарий 2: Реализация WS-Ping в вашем приложении
Даже с большими тайм-аутами Nginx, промежуточные роутеры могут убить TCP-сессию. Ваше приложение ОБЯЗАНО периодически отправлять WebSocket Ping (или Pong) кадры на сервер Asterisk для поддержания активности.
- В Node.js (библиотека
ws): настройте интервал (setInterval) на отправкуws.ping()каждые 30 секунд. - В Python (библиотека
ari-pyилиwebsockets): используйте параметрping_interval=30.
Сценарий 3: Настройка Asterisk (http.conf / ari.conf)
# /etc/asterisk/http.conf
[general]
enabled=yes
bindaddr=127.0.0.1 ; Не слушайте 0.0.0.0, проксируйте через Nginx
bindport=8088
session_inactivity=3600
# /etc/asterisk/ari.conf
[general]
enabled = yes
pretty = yes
[my_app_user]
type = user
read_only = no
password = StrongAriPassТиповые ошибки разработчиков
- Отсутствие Reconnect-логики: Сети нестабильны по определению. Если ваше приложение (Stasis App) не умеет автоматически переподключаться к ARI при обрыве соединения, вся логика звонков встанет колом.
- Блокировка Event Loop: В синхронных языках долгая обработка одного события (например, долгий SQL-запрос) заблокирует чтение сокета. Asterisk переполнит буфер и принудительно закроет соединение с клиентом.
Разработка отказоустойчивых коммуникационных платформ требует глубокого понимания архитектуры Stasis. Разработчики ITSTM спроектируют надежную микросервисную архитектуру интеграции Asterisk, исключив потери событий и зависание вызовов.
Частые вопросы (FAQ)
Опасна ли ошибка 'websocket read error: success'?
Если она появляется редко (при рестарте приложения или смене IP) — это нормально. Если она сыпется постоянно во время активных звонков — это критично, так как ваше приложение теряет контроль над каналом, и звонок либо 'повиснет', либо завершится некорректно.
Нужно ли использовать WSS (Secure WebSocket) внутри локальной сети?
Между локальным Nginx и Asterisk достаточно обычного WS (HTTP). Но наружу (если приложение крутится в облаке) обязательно проксируйте через Nginx с сертификатом TLS, превращая трафик в WSS (HTTPS).
Почему после реконнекта ARI приложение не видит старые звонки?
Это специфика Stasis. При потере соединения приложение теряет подписки на события каналов. При реконнекте необходимо запрашивать список активных каналов (GET /channels) и заново привязывать их к приложению.
Как включить дебаг WebSocket в Asterisk?
В CLI Asterisk выполните команды: 'http show status' и 'ari set debug all'. Это позволит увидеть сырые JSON-объекты, которые ходят между сервером и приложением.