RealTime в Asterisk: архитектура и конфигурация

RealTime в Asterisk: архитектура и конфигурация с 5 октября по 9 октября

Количество
свободных мест

8 Записаться

Курсы по Mikrotik MTCNA

Курсы по Mikrotik MTCNA с 6 апреля по 10 апреля

Количество
свободных мест

7 Записаться

Курс по Zabbix

Zabbix: мониторинг Asterisk и VoIP с 7 сентября по 11 сентября

Количество
свободных мест

8 Записаться
Решение проблем при распределённой работе с большими списками данных
26
Доклад
Дмитрий Жуков
Решение проблем при распределённой работе с большими списками данных

Работа современных колл-центров — это не просто звонки, а бесконечный поток данных. Сообщения из чатов, статусы операторов, системные события от АТС — всё это сыпется в систему в виде огромного количества «джейсончиков». Чтобы превратить этот хаос в нормальную аналитику, которую сможет понять супервайзер или обычный оператор, нужно не просто «складировать» информацию, а правильно её готовить. Главная головная боль тут — работа с однотипными данными. Юзер-ивенты, сообщения в мессенджерах, логи очередей — они все вроде бы похожи по структуре, но их прилетает настолько много, что обычные методы «в лоб» быстро перестают работать.

Когда данных становится слишком много, система начинает тормозить, браузеры операторов «отъедают» память, а данные на разных вкладках начинают жить своей жизнью. Чтобы разгрести эти завалы, был придуман внутренний инструмент под названием «Курсор». Это не просто библиотека, а целая модель того, как нужно обращаться со списками в распределенных системах, чтобы всё летало, не тупило и всегда было актуальным. В основе лежит идея, что нам не важно, что именно лежит в списке — будь то история чата или установка Asterisk с её логами — подход к управлению этими данными должен быть универсальным.

Обычные списки — это боль

Главная проблема больших списков в реальном времени — это синхронизация. Представьте колл-центр, где у оператора открыто пять вкладок в браузере. Если в одной вкладке пришло сообщение, оно должно мгновенно появиться во всех остальных. Если просто дёргать API на каждый чих, бэкенд быстро «приляжет» от нагрузки. А если хранить всё в памяти браузера, то через пару часов работы оператору придётся перезагружать страницу, потому что вкладка займёт пару гигабайт оперативной памяти.

Основные вызовы при работе с потоками данных:

  • Синхронность: все клиенты должны видеть одно и то же состояние данных в одну и ту же секунду.
  • Производительность: слабые рабочие станции не должны зависать при скроллинге списка из 100 000 элементов.
  • Гибкость: сегодня мы выводим чаты, завтра — очереди, послезавтра — логи звонков. Инструмент не должен переписываться под каждую новую «хотелку» бизнеса.

Чтобы всё это работало, нужно было уйти от жестких схем. «Курсор» работает с абстрактными данными. Ему по большому счету всё равно, что внутри объекта. Главное, чтобы у объекта был уникальный ключ (ID), чтобы отличать одну запись от другой, и правила сортировки, чтобы понимать, в каком порядке эти записи выстраивать. Это позволяет использовать один и тот же код и для фронтенда, и для бэкенда, что сильно упрощает жизнь разработчикам.

Архитектура: как построить дерево и не запутаться

Чтобы данные не разлетались, в системе выстроена иерархия инстансов (экземпляров) инструмента. Это похоже на дерево, где есть главный «корень» на сервере и множество «листьев» в браузерах пользователей. Такая структура позволяет передавать только то, что действительно нужно, и не гонять лишний трафик по сети.

Когда пользователю нужно посмотреть, например, список активных очередей, в его браузере создается инстанс «Курсора». Но он не ломится сразу в базу данных. Сначала он ищет «старшего товарища». В рамках одного браузера такой ролью наделяется хост-вкладка. Это самая первая открытая страница, которая берет на себя всё общение с сервером. Все остальные вкладки (дочерние инстансы) просто подписываются на неё.

Как это работает под капотом:

  1. Событийная модель: когда на бэкенде что-то меняется (например, пришел новый звонок), событие летит вниз по дереву. Инстансы просто слушают канал и обновляют свои данные.
  2. RPC-запросы: если оператору нужно что-то изменить (написать ответ в чат или сменить статус), запрос уходит вверх к «родителю», пока не достигнет бэкенда, который запишет данные в БД.
  3. Изоляция: каждый узел в этом дереве знает только о своем «родителе» и своих «детях». Ему не нужно знать всю топологию сети.

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

Четыре слоя данных: как сберечь память оператора

Самая интересная часть — это то, как «Курсор» экономит память. Если мы загрузим 50 000 сообщений из чата со всей их логикой, методами обработки и связями, браузер просто упадет. Поэтому данные в инструменте хранятся слоями, как в пироге. Детализация объекта зависит от того, насколько он сейчас нужен пользователю.

Уровни детализации «Курсора»:

  • UI-слой (самый «жирный»): это объекты, которые пользователь видит прямо сейчас на экране. У них есть все методы, они обложены логикой, они готовы к взаимодействию. Таких объектов в памяти всегда мало — ровно столько, сколько влезло в видимую область экрана плюс небольшой запас сверху и снизу.
  • Raw-слой (сырые данные): это просто объекты с данными, без всяких методов. Они лежат в памяти «на всякий случай», если пользователь начнет скроллить. Они занимают в разы меньше места, чем UI-объекты.
  • Instructions-слой (инструкции): здесь нет самих данных, только мета-информация о том, как их получить. Например, параметры для fetch-запроса. Если пользователь доскроллит до этого места, система поймет: «Ага, пора идти за данными».
  • Summary-слой (сводка): самый легкий уровень. Это просто знание о том, что где-то там в конце списка есть еще 10 000 элементов. Это нужно, чтобы правильно отрисовать полосу прокрутки (скроллбар). Вы видите, что список огромный, но ваш компьютер об этом не «парится», пока вы туда не доскроллите.

Когда вы крутите колесико мышки, объекты постоянно перемещаются между этими слоями. UI-объект, уходя из зоны видимости, превращается в Raw, потом в Instruction, и в конце концов остается только запись в Summary. Это позволяет бесконечно скроллить чаты за несколько лет, и страница при этом не будет тормозить. В таких ситуациях приоритезация трафика QoS помогает сообщениям подгружаться быстро, не создавая задержек в интерфейсе.

Универсальный язык запросов: от фронта до базы

Еще одна крутая фишка — это то, как реализованы фильтры и сортировка. Обычно для фронтенда пишут одну логику фильтрации (на JavaScript), а для бэкенда — другую (на языке базы данных, например, SQL или NoSQL). В «Курсоре» решили от этого уйти и сделали универсальный синтаксис, очень похожий на то, как запросы пишутся в MongoDB.

Зачем это нужно? Чтобы разработчику не приходилось каждый раз думать, где именно будет происходить фильтрация. Он просто описывает условие: «хочу все сообщения от пользователя X за вчера». Инструмент сам понимает:

  • Если данные уже загружены в память (Raw или UI слой), он отфильтрует их локально, не дергая сервер.
  • Если данных в памяти нет, он преобразует этот запрос в формат, понятный базе данных (например, в объект для Mongoose или строку для SQLite), и отправит его на бэкенд.

С сортировкой та же история. Она бывает внешняя (когда база данных присылает нам уже готовый упорядоченный список) и локальная (когда мы прямо в браузере меняем порядок элементов, например, по дате или приоритету). Это дает невероятную гибкость. Если проводится аудит IP-ATC и нужно быстро найти подозрительную активность в миллионах логов, такие универсальные фильтры позволяют выдернуть нужную информацию за доли секунды, не перегружая систему сложными запросами.

Практика: чаты, очереди и «дырки» в данных

Как всё это выглядит в реальности? Возьмем обычный чат. Пользователь открывает историю переписки. «Курсор» сразу рисует скроллбар нужного размера, хотя самих сообщений в памяти еще нет — он взял информацию из слоя Summary. Как только пользователь начинает листать, «Курсор» по цепочке инстансов передает запрос: «Дайте данные для этого диапазона».

Самое важное, что система умеет работать с «дырками». Если пользователь резко прыгнул в начало переписки трехлетней давности, инструмент не будет скачивать всё, что было посередине. Он просто создаст островок данных (UI-слой) в нужном месте, а всё остальное оставит в виде легких «инструкций» или «сводки».

Для управления очередями в Asterisk всё работает еще проще. Там данных меньше, чем в чатах, но они меняются чаще. Благодаря древовидной структуре инстансов, любое изменение статуса оператора (ушел на перерыв, принял звонок) долетает до всех мониторов мгновенно. Причем бэкенд-инстанс может брать эти данные напрямую из оперативной памяти или Redis, а фронтенд-инстанс даже не будет знать об этих тонкостях — он просто получит обновленный «джейсончик» и обновит картинку.

Такой подход позволяет строить действительно масштабируемые продукты. Не важно, сколько у вас операторов — десять или тысяча. Правильная организация потоков данных, разделение на слои и умная синхронизация позволяют интерфейсам оставаться отзывчивыми, а бэкенду — стабильным. Если вы хотите глубже погрузиться в тему настройки подобных систем, курсы по Asterisk помогут разобраться с тем, как генерируются те самые первичные данные, которые потом так ловко обрабатывает «Курсор».

 

Заключение

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

Использование таких подходов — это не просто дань моде, а необходимость в мире, где объем информации растет экспоненциально. Когда система спроектирована так, что она «знает» о данных ровно столько, сколько нужно в конкретный момент, она становится практически неубиваемой. Это дает возможность бизнесу не тратиться на бесконечный апгрейд серверов и компьютеров сотрудников, а сосредоточиться на качестве обслуживания и новых фичах.

Ежегодная конференция по Asterisk 2026!

Билеты уже в продаже!

Остались вопросы?

Я - Игорь Кондрашин, менеджер компании Voxlink. Хотите уточнить детали или готовы оставить заявку? Укажите номер телефона, я перезвоню в течение 3-х секунд.

Наши
клиенты

Посмотреть все