Сегодня речь пойдет о mediation-системах — системах обработки больших данных класса OSS/BSS (Operations / Business Support System). Они получают данные из разнородных источников, обрабатывают в зависимости от требований и передают в нужном формате в другие системы-потребители. Чаще всего их применяют в телеком-сфере: они собирают информацию об абонентском трафике, который условно можно разделить на две группы: голосовой и передача данных (интернет), преобразуют, а затем отправляют в биллинговую систему для выставления счетов. Поэтому такие системы называют предбиллинговыми. Но их возможности также применяют для автоматизации в логистике, сфере коммунальных услуг или финансов. И вообще везде, где нужно собирать большие объемы разнородных данных, а потом в преобразованном виде отправлять в другие системы. В этой статье поговорим именно о телекоме, а в будущих я расскажу и про стриминг-платформы, и про интернет вещей, и про другие сферы. Исторически сложилось, что бОóльшую часть российского рынка mediation-систем занимает OpenView Internet Usage Manager от HP (HP IUM). Именно на нем работает большинство телеком-операторов и интернет провайдеров.  После ухода зарубежных вендоров вопрос разработки отечественных mediation-систем проявился особо остро. Но на самом деле он назревал давно, и дело тут не только в импортозамещении. HP IUM был разработан пару десятилетий назад и постепенно перестал соответствовать современным требованиям. Телеком-индустрия движется вперед: растут объемы и скорость передачи данных, меняются стандарты и протоколы, инфраструктура обрастает сервисами и становится все сложнее. А объемные монолитные системы предыдущего поколения не успевают за этими изменениями и мешают развитию бизнеса за счет множества ограничений: Они заточены только под вертикальное масштабирование, а попытки масштабировать их в горизонталь упираются в пределы серверных мощностей Обычно у таких систем единая база данных, приложения взаимодействуют с ней синхронно, запросы выполняются последовательно — это снижает скорость обработки данных Весь монолит написан на одном языке, а значит невозможно написать отдельный модуль на другом языке, даже если это выгоднее и актуальнее.  При сбое в любом модуле монолита вся система выходит из строя — в отличие от микросервисных продуктов, где модули меньше влияют на общую работоспособность Да и в целом монолиты не отличаются гибкостью: добавление поддержки нового протокола или изменение логики обработки превращается в масштабные задачи и большие циклы разработки. Еще одна проблема —  устаревший технологический стек и использование закрытых проприетарных компонентов, которые часто уже не поддерживаются и/или не развиваются вендором Отсутствие RESTful API (его просто не существовало, когда эти системы разрабатывали) приводит к сложностями интеграции, мешает связывать разнородные системы и выстраивать качественный ИТ-ландшафт. Вишенкой на торте — неудобный устаревший UI/UX. Во многих легаси-решениях web-интерфейс, если он вообще есть, остался на уровне web 1.0. Но чаще управление осуществляется с помощью десктопных приложений на каждом рабочем месте. Это усложняет поддержку, повышает издержки. В общем, напрашивалось создание новых и удобных систем обработки данных, которые с легкостью подстраиваются под требования заказчика и индустрии, при этом удобны в управлении и надежны и эффективны в работе.  Конечно, искать недостатки в чужих решениях и строить концептуальные теории легко. Куда сложнее предложить целостное готовое решение. Мы в STM Labs с 2011 года занимаемся разработкой, интеграцией и поддержкой mediation-систем и изучили телеком-сферу изнутри. Мы не понаслышке знаем обо всех достоинствах существующих mediation-решений и способах справиться с их недостатками. Поэтому мы создали Pi.One — отечественную платформу предбиллинга, превосходящую зарубежные аналоги. Функционально Pi.One решает все задачи, присущие mediation-системам:  собирает, преобразует и отправляет данные — быстро, гибко и без потерь. А еще у Pi.One удобный интерфейс и понятная подробная документация. Все это позволяет оптимизировать ресурсы, стандартизировать бизнес-процессы  и сконцентрировать усилия на ключевых задачах бизнеса. Pi.One внесен в Реестр Российского ПО и имеет сертификат соответствия от Минсвязи. Система успешно применяется в реальных проектах, например — обеспечивает надежность и точность передачи данных в составе mediation-платформы российского телеком-оператора из большой четверки. На этом переходим к техническим деталям.  Docker-сервисы внутри развернутого кластера K8S Встроенный интерфейс мониторинга для оператора системы  Поддержка интеграции с современными системами мониторинга и логирования (Prometheus, Loki и др.) в ландшафте заказчика Гео-распределенный режим в состоянии Active-Warm Standby Поддерживает масштабирования элементов архитектуры в горизонт для обеспечения высокой производительности и надежности при обработке Сбой в работе одного микросервиса не приводит к сбоям в работе всей системы В современных решениях важно использовать проверенные в бою open source компоненты. Они активно развиваются и поддерживаются сообществом и крупными вендорами.  Pi.One полностью независим от проприетарных решений сторонних вендоров. Используются только проверенные Open Source решения с большим комьюнити. Из коробки Pi.One работает с протоколами и интерфейсами всех ведущих поставщиков телеком-оборудования: Diameter, HTTP/2, WebSocket, HTTP, TCP/IP, MQTT, FTP, SFTP, FTAM, TCP/IP, SNMP, SMTP, GTP, SCP, SOAP, Radius, Web-сервисы и др Pi.One может взаимодействовать с брокерами сообщений — такими как Apache Kafka. Также поддерживается взаимодействие с NoSQL базами данных: Redis, CouchBase и др. Если нужна поддержка других протоколов или дополнительные компоненты, их можно легко добавить благодаря модульной архитектуре решения. Перед обработкой данные, полученные из внешних источников, декодируются во внутренний формат IDR (Internal Data Records), с которым работает вся дальнейшая бизнес-логика. По сути на этапе декодирования данные из внешних источников превращаются в объекты в том виде, в котором они они обрабатываются в блоках бизнес-логики. Для определения формата данных из внешних источников, внутреннего формата, в который эти данные надо преобразовать, а также для описания правил преобразования мы используем Pi.Lang.  После того как IDR поступает в рабочий поток Pi.One, где происходит его обработка согласно бизнес-логике и после этого он снова может быть закодирован во внешний формат (скорее всего отличающийся от входного) для систем потребителей данных.   Таким образом, система способна получать и отправлять данные в любых необходимых внешних форматах, и это не влияет на точность обработки. Пакетная (интервальная) — это метод, используемый для периодического выполнения больших объемов повторяющихся заданий с данными. Некоторые задачи обработки данных, такие как фильтрация и сортировка, могут быть требовательны к ресурсам и неэффективными для выполнения отдельных транзакций. Вместо этого рабочий поток обрабатывает такие задачи пакетно — порциями данных. Потоковая — предполагает работу с данными в режиме реального времени. Когда размер передаваемых данных неизвестен или бесконечен, потоковая обработка может быть предпочтительнее пакетной обработки. В результате потоковая обработка обычно используется в задачах, постоянно генерирующих потоки данных. Транзакционная целостность Обработка данных внутри системы осуществляется в соответствии с механизмом, гарантирующим безопасную и полную обработку данных, без дублирования и потерь.  Встроенная пользовательская ролевая модель предполагает гибкое разграничение доступа к компонентам системы. Поддерживается интеграция с Active Directory, LDAP. В системе фиксируются и журналируются все действия пользователей, внесенные изменения параметров и результаты обработки данных. Доступны инструменты гибкой настройки аудита обрабатываемых данных. Вся работа по получению, обработке и доставке данных в Pi.One осуществляется с помощью рабочих потоков. Каждый рабочий поток строится из агентов, которые выполняют определенные задачи: собрать файлы из директории, убрать дубликаты в файлах, агрегировать данные, доставить файлы в папку на удаленном сервере и т.д. Большая часть бизнес-логики задается с помощью настраиваемых lowcode-агентов, выполняющих операции над данными. Создать собственную стратегию сбора данных можно, используя Groovy. Это позволяет отфильтровывать лишние файлы еще на этапе их сбора. Можно произвести и дедубликацию на уровне файлов, для этого есть отдельный nocode-агент дедубликации. Также Pi.One имеет широкие возможности для агрегации данных — в  настройках агента агрегации достаточно прописать по каким полям IDR нужно производить агрегацию. Также есть возможность описать дополнительные действия с помощью Groovy-кода, это позволяет отсеять одинаковые записи на уровне файла или файлов (в зависимости от задач), кэшировать уже обработанные данные для дальнейших манипуляций с ними. Например, если в двух разных файлах содержится время начала и время окончания звонка, а нужно посчитать его длительность и сформировать запись в файле для системы потребителя только поступления файла с записью о завершении звонка. Именно из таких nocode и lowcode-агентов в конструкторе Pi.One наглядно проектируются сложные рабочие потоки с помощью функциональности Drag & Drop.  Как я упоминал выше, одной из ярких черт легаси-систем является неудобный интерфейс. В современных решениях разработке UX/UI уделяется огромное внимание: вне зависимости от того, насколько сложный бэк у системы, пользователю должно быть удобно ей управлять.  Именно на этом принципе строится интерфейс Pi.One: Данные представляются в графическом минималистичном виде. На рабочем экране нет лишних элементов и информации. Рабочие потоки и конфигурации распределяются по проектам. Доступ к проектам гибко настраивается для каждого сотрудника.  Управление и навигация между группами потоков, потоками, библиотеками и другими элементами интерфейса интуитивно понятны.  Рабочие потоки можно объединить в группы потоков и гибко настроить расписание и условия для автоматического запуска обработки. В результате после настройки и отладки системы, ее эксплуатация заключается только в мониторинге работы, с которым справится всего один оператор.  В пакете с системой поставляются материалы для подготовки команды заказчика к работе с Pi.One в кратчайшие сроки: документация, видеоматериалы и поддержка на русском языке. Минималистичная и понятная документация доступна в адаптивной web-версии и формате pdf. На соответствующие страницы можно перейти через поиск или прямо из интерфейса Pi.One. Но давайте не будем голословными и рассмотрим процесс реализации потоковой обработки данных на Pi.One. Нам нужно было сделать что-то для выставки CSTB.Pro.Media 2023. Что-то такое, что покажет возможности Pi.One как платформы. И мы решили сделать телеграмм-бота.  Что же должен уметь наш бот?  Регистрировать нового подписчика Поддерживать команду пополнения баланса Предоставлять возможность купить контент Предоставлять возможность посмотреть какой контент уже куплен Давать возможность просматривать купленный контент Помимо этого необходима некая интеграция с CRM-системой, чтобы отображать аналитику по выручке и количеству покупок контента. Кроме того мы решили, что было бы здорово хранить логи в S3 Minio. Естественно, мы не стали реализовывать реальную цепочку пополнения баланса и оплаты с использованием банковских систем. Так же, как и не стали реализовывать подключение контента через DRM, а CRM быстро набросали, чтобы отображать красивые графики. Основная суть была показать, что основной каркас приложения для решения такой задачи можно написать за несколько часов.  В качестве БД мы использовали Postgres, хотя по факту можно было выбрать любую SQL или NoSQL базу данных. Также нам было необходимо два рабочих потока: первый — это бэкенд для нашего бота, второй предоставляет REST API для нашей импровизированной CRM системы. Весь код писался максимально быстро, мы знаем, что можно написать лучше. Наша цель была показать возможности системы, а не красоту кода Создание любого проекта на Pi.One проще всего начинать с создания различных профилей. Вот с них то и начнем. Создаем файл, где будем хранить данные для подключения к БД и к Minio Теперь создаем профиль внешних параметров, чтобы можно было обращаться к данным из нашего файла Еще нам потребуется профиль базы данных (с его помощью мы можем работать непосредственно с самой Postgres, и он возьмет на себя все наши заботы по открытию, закрытию соединения, выполнению запросов и прочим вещам, на которые нам не хочется тратить время) и профиль для S3 Minio. Сделаем их. Итак, профили готовы, описываем структуры данных через Pi.Lang. Вот, например, формат с которым мы работаем в потоке, предоставляющем REST API для нашей импровизированной CRM: DashboardResponse это, собственно, описание тела нашего ответа. Позднее мы его декодируем в json и отправим в ответ на запрос. Теперь пришло время для создания рабочих потоков бэкенда телеграм-бота: Коротко пройдемся по тому что есть. Init — это агент, генерирующий события с заданной частотой. Он нам нужен для того, чтобы определить порядок выполнения бизнес-логики и запустить обработку команд от бота. Любой рабочий поток устроен так, что порядок выполнения всех агентов определяется относительно входного агента. Это может быть REST сервер, агент обработки Diameter запросов, агент сбора файлов по SFTP и т.п. Telegram_Bot — Groovy-агент, принимающий команды от нашего бота. Для реализация взаимодействия с Telegram выбрана библиотека https://github.com/rubenlagus/TelegramBots/tree/master Вот часть кода этого агента: GroovyExectuion — основной класс нашего агента, при добавлении базовый код генерируется автоматически.  Метод initialize() определяет бизнес-логику при запуске рабочего потока. Выполняется один раз при запуске приложения. Метод consume() выполняется постоянно во время работы потока. Метод deinitialize() выполняются при завершении работы потока. Для отправки данных другим агентам мы используем встроенную функцию idrRoute, принимающую два параметра: объект, который нам надо отправить, и имя пути, по которому эти данные надо отправить. В нашем примере она спрятана в TelegramMessageProcessing. Вот кусок кода из этой функции: Запрос от пользователя отправляется к другому Groovy-агенту — Processing. В нем реализована бизнес логика по определению подключенного и доступного контента, определению баланса и реакции на команду, которую ввел пользователь. Вся бизнес-логика выглядит вот так: На самом деле весь код вынесен в отдельный groovy-модуль TelegramUtils, да его импорт вы видите в самом начале. Вот кусок кода из этого модуля: Объект PiTable — это встроенный объект Pi.One, который позволяет работать с таблицами любых БД. Есть множество встроенных функций для работы с БД.  tableCreate, позволяющая создавать таблицу на основании профиля БД, tableLookup для поиска данных в таблицах по определенным условиям,  tableGet для получения данных из таблицы.  также есть функция для выполнения sql запросов в БД - sqlExec, туда достаточно передать имя профиля БД, который мы настраивали в самом начале (в нашем случае это будет ‘CSTB_Workshop.PRF_DB_Common’) и sql запрос, который мы хотим выполнить, если нужно выполнить запрос в рамках транзакции, это решается передачей аргумента enableTransaction в вызове функции sqlExec. если нужно что-то вставить в таблицу, то будет выглядеть все примерно так: sqlExec( ‘CSTB_Workshop.PRF_DB_Common’, ‘UPDATE myTable SET counter = 5’, true) Закончили с этим, пишем рабочий поток для REST API нашей CRM. Он будет совсем простым — всего два агента.  Агент RestServer — в нем задаем настройки на каком ip-адресе и порту будет поднят наш REST API, в настройках можно настроить TLS и Oauth 2.0 авторизацию. Также есть возможность привязать профиль REST-агента, в котором прописать допустимые URI, при обращении к другим URI-агент автоматически будет возвращать 404 HTTP код   Выглядит это так: Отдаем фронтенду спеку на наше REST API, просим сделать красиво, но быстро, и вот что получается. Groovy-агент с бизнес-логикой достаточно простой, знакомый нам уже GroovyBase с теми же самыми методами consume и теми же самыми PiTable Из интересного тут то, что объект RestServer формируется автоматически нашим RestServer-агентом при каждом новом запросе. RestServerRequest содержит данные запроса endpoint, заголовки, тело. RestServerResponse — еще один встроенный тип в Pi.One. Чтобы отправить ответ клиенту на его запрос, нужно создать новый объект этого типа, выполнить set_response для входного объекта и отправить его назад на наш RestServer-агент с помощью idrRoute. Вот так мы формируем ответ. Встроенная функция jsonEncodeIdr позволяет одним вызовом превратить объект нашего внутреннего формата в json. Почти как jackson, но без всяких аннотаций 🙂 Теперь все готово, можно выдохнуть, отдать описание API фронтендеру, чтобы он сделал нашу импровизированную CRM. Кстати, вот она:  Класс, все работает. Итак, сколько же мы потратили на это времени?  Придумать архитектуру — во время обеда поболтать с коллегами и найти решение Реализация бэка для бота — 5 часов, из которых час-полтора потратили на изучение java-класса для взаимодействия с телеграм-ботом Реализация REST API для CRM — 3 часа (с перерывом на чай) Итого получается, что за рабочий день мы смогли реализовать на Pi.One бэкенд для телеграм-бота и REST API для импровизированной CRM. А теперь немного типичных вопросов, которые нам обычно задают, когда мы рассказываем про наш продукт: А в чем ваше преимущество перед HP IUM? Наше преимущество в том, что мы предоставляем более гибкое решение просто благодаря наличию Groovy-агентов, на которых можно реализовать любую бизнес-логику. Вам не придется писать пользовательские java-классы в случае каких-то нестандартных требований к обработке и продираться сквозь необходимость наследоваться от абстрактных классов IUM и перегружать уйму методов. Groovy? Придется инженеров, эксплуатирующих систему, учить программированию.  Groovy — простой язык программирования, имеющий достаточно низкий порог входа (по моему личному мнению сопоставимый со всеми известным своей простотой для новичков Python). Кроме того в состав Pi.One входит достаточно большое количество готовых и протестированных функций, существенно облегчающих понимание кода. В любом случае понять Groovy-код в Pi.One существенно проще, чем понять код пользовательского java-класса на HP IUM. Еще Pi.One снимает с разработчика проблемы связанные с многопоточностью, управлением соединениями с БД, транзакционной целостностью обработки, что делает написание Groovy-кода еще проще. А как насчет CI/CD? Мы используем git для хранения проектов внутри Pi.One. Это позволяет нам интегрироваться c CI/CD системами, например GitLab CI. У Pi.One есть REST API, позволяющее запускать и останавливать рабочие потоки, возвращать их состояние и получать информацию о некоторых переменных рабочего потока. Это дает возможность запустить новую версию в песочнице, прогнать автотесты, чтобы убедиться что все работает и разворачиваться дальше. Таким образом можно в кратчайшие сроки добавлять или обновлять функционал, исходя из потребностей заказчика. При разработке Pi.One мы, конечно же, опирались на опыт систем предыдущих поколений — сохранили весь привычный функционал и дополнили его новыми возможностями. Он обеспечивает точную и быструю обработку огромных объемов данных, позволяя телеком-операторам снижать издержки и повышать качество своих услуг. Но так же мы учли и слабые места прошлых mediation-систем, главным образом — сложности с масштабированием и гибкостью в новых реалиях.  Поэтому одним из основных преимуществом Pi.One я считаю его гибкость. Его просто адаптировать под любые задачи заказчика и требования индустрии. Добавить новые протоколы и интерфейсы, масштабировать при изменении объемов данных, изменить процесс обработки, подключить новый функциональный модуль или интегрировать в ИТ-ландшафт новый сервис — все это не является проблемой благодаря микросервисной архитектуре и проверенным современным технологиям.  Таким образом, Pi.One не только соответствует требованиям, которые телеком-индустрия выставляет сегодня, но и способен подстроиться под будущие изменения. Именно эта способность гарантирует долгосрочное и успешное функционирование и позволит телеком-операторам оставаться конкурентоспособными на рынке на протяжении многих лет. Если у вас тоже есть вопросы (наверняка появились!), с удовольствием готов ответить и обсудить в комментариях.