Русский
Русский
English
Статистика
Реклама

Мтс

Из чего состоит набор для разработчиков NB-IoT DevKit?

26.06.2020 12:10:59 | Автор: admin
Набор вышел в начале июня. Он поможет разобраться, в чем преимущества сети интернета вещей NB-IoT, и научит работать с ней. В комплект входит аппаратная часть, коннективити, то есть доступ к сети NB-IoT и доступ к IoT-платформам. Главная фича DevKit демонстрационная прошивка, которая позволяет на практике разобраться, как работает система. В этой статье детально рассмотрим DevKit и его возможности.



Кому это надо?


Когда мы начали разворачивать сеть NB-IoT (почитать больше о сети NB-IoT можно здесь), на нас со всех сторон посыпались различные вопросы. Крупные производители, которые много лет работают на рынке M2M устройств, стартапы, начинающие разработчики и просто любители интересовались режимами работы сети, протоколами передачи данных, даже управлением радиомодулем АТ-командами. Нас спрашивали, какие частоты (band) используются, как работает режим power save mode, как устройство и сеть согласуют соответствующие таймеры, как, используя протокол транспортного уровня UDP, добиться гарантированной доставки сообщения, как задать APN и выбрать определенный band (частотный диапазон). И множество других вопросов.

В ходе тестов мы также обратили внимание, что многие устройства не адаптированы для работы в сети NB-IoT и в результате работают некорректно. Например, использование протокола передачи данных с транспортным уровнем TCP приводит к высокому объему передаваемого трафика, а также к трудностям при работе в сложных радиоусловиях. Другая распространенная проблема использование радиомодуля в режиме по умолчанию, в котором модуль сам включает eDRX: это вводит пользователя в заблуждение, так как он не может принять данные в произвольный момент времени.

К нам стали обращаться ВУЗы, специализирующиеся на телекоммуникациях, которым интересно изучить на реальных устройствах технологии LPWAN, в том числе NB-IoT, и разработчики-любители, которые хотят поэксперементировать и создать собственное IoT-решение для умного дома или даже умного города.

Мы решили, что лучший способ ответить на все эти вопросы создать development kit, на котором можно будет максимально быстро научиться работать с сетью интернета вещей.

Из чего состоит набор?


Мы сделали решение, с которым можно сразу начинать работать, ничего не приобретая дополнительно. Как уже говорилось выше, в комплект входит аппаратная часть, коннективити, то есть доступ к сети NB-IoT, и доступ к IoT-платформам.

В состав аппаратной части входит радиомодуль Ublox SARA-R410, микроконтроллер STM32L152RE, кабели, антенны и программатор. На основной плате установлены акселерометр и температурный датчик. Плата расширения в форм-факторе Arduino-shield содержит GNSS модуль.

Модуль идентификации в сети входит в базовый набор и выполнен в виде SIM-чипа NB-IoT с безлимитным трафиком на год. Пользователю не нужно тратить время на подключение SIM-карты и выбирать тариф, кроме того, SIM-чип обеспечивает большую надежность: он не подвержен перепадам температур, влажности и вибрациям. Также вместе с комплектом пользователь получает готовую учетную запись на платформе IoT с настроенными виджетами и возможностью гибко настраивать виджеты самостоятельно дополнительно получать и оплачивать аккаунт не потребуется.

Также по запросу возможна активация функционала NIDD и возможность работы через узел SCEF (Service Capability Exposure Function) сети NB-IoT МТС. Сервис снимает с разработчика необходимость идентификации и аутентификации устройств и предоставляет возможность клиентским серверам приложений (Application Server) получать данные и управлять устройствами через единый API-интерфейс. В России ни один другой оператор интернета вещей не предоставляет такую возможность.

Возможности демонстрационной прошивки


Демонстрационная прошивка содержит функциональное меню, которое позволяет новичкам сразу приступить к работе. Достаточно лишь подключить плату и получить регистрационные данные. Прошивка реализует функциональное меню, доступ к которому мы получаем, подключившись через любую терминальную программу. Можно воспользоваться знакомой многим PuTTY. Мы также рекомендуем удобную и бесплатную утилиту от Ublox: m-center



Выглядит меню так:

*** Welcome to MTS NB-IoT Development Kit service menu ***
Firmware version: 2.3 beta 2, 28.05.2020

Current settings found in EEPROM:

Target IP: 195.34.49.22
Target port: 6683
Target URL: /api/v1/devkitNIDDtest03/telemetry
NIDD APN: devkit.nidd
Use NIDD for telemetry: 1
Board mode on startup: service menu
Telemetry interval
(in logger mode): 1000 ms
GNSS privacy mode: 0

Type in a function number from a list below and press enter.

Target server setup:
1 set the URL of the resource JSON data will be transmitted to
2 set the IP address
3 set the port
4 set an APN for NIDD access or turn NIDD mode ON or OFF
System functions:
5 force send telemetry packet
6 wait for incoming NIDD data during specified timeout
7 enter direct AT-command mode
8 enter true direct mode to access the RF module
CAUTION: to exit this mode you will have to reboot the board physically
9 show ICCID, IMEI, IMSI and MCU serial number
10 show network information
11 set telemetry transmission interval
12 set GNSS privacy mode
(hide actual location data when transmitting on server)
13 set firmware startup mode (setup or logger)
14 read on-board sensors and try to acquire GNSS data
15 reboot MCU
16 reboot RF module
17 factory setup & test
(do not use this unless you really know what you want)

Первые четыре пункта меню позволяют настроить параметры соединения с платформой (URI-path, IP, порт, параметры NIDD). Пятый пункт позволяет отправить пакет, содержащий данные с датчиков на плате.

Пример того, как выглядит результат отправки пакета по протоколу CoAP:

Using IP method.
Sending data to iotsandbox.mts.ru:6683/api/v1/devkitNIDDtest03/telemetry
Telemetry:
{'interface':'telemetry', 'ICCID':'89701012417915117807', 'Tamb_degC':24, 'aX':-14, 'aY':23, 'aZ':244, 'RSSI_dBm':-81, 'latitude':55.768848, 'longitude':37.715088, 'GNSS_data_valid':1}
(184 bytes)
Raw CoAP data (225 bytes):
5102000000B36170690276310D036465766B69744E4944447465737430330974656C656D65747279FF7B27696E74657266616365273A2774656C656D65747279272C20274943434944273A273839373031303132343137393135313137383037272C202754616D625F64656743273A32342C20276158273A2D31342C20276159273A32332C2027615A273A3234342C2027525353495F64426D273A2D38312C20276C61746974756465273A35352E3736383834382C20276C6F6E676974756465273A33372E3731353038382C2027474E53535F646174615F76616C6964273A317D
Server response code: 2.03, response time = 664 ms.
Server response dump:
5143067000

Переданные данные мы видим на платформе:



Пункт меню 14 позволяет считать данные с датчиков на основной плате и на плате расширения, вот пример того, что мы увидим:

On-board sensors data:
temperature: 23

accelerometer: X = -3 Y = 4 Z = 249
Accelerometer signature value is correct.

Testing GNSS option
GNSS string:
$GNGLL,5546.12120,N,03742.89412,E,133220.00,A,D*75
Parsed data:
latitude = 55.768687
longitude = 37.714902

Можно прочитать идентификаторы радиомодуля и микроконтроллера, используя пункт 7 меню. В таком случае ответ будет:

Board identification data
SIM card ICCID: 89701012417915117807
AT+CCID

+CCID: 89701012417915117807

OK
RF module IMEI: 359215103260015
AT+CGSN

359215103260015

OK
IMSI:
AT+CIMI

250011791511780

OK
MCU serial number:
0x393533307473832200

Используя пункт 10 меню можно считать сетевые параметры NB-IoT, вот пример вывода:

RSSI = -75 dBm (valid range is -111 to -51 dBm)
SNR = 22 dB
RSRP = -83 dBm (valid range is -141 to -44 dBm)
Cell ID = 753621
EARFCN = 1711

Также можно перейти в режим прямого управления радиомодулем посредством АТ-команд, используя пункт меню 8. Эта функция переводит Development kit в режим отладочной платы радиомодуля. Ниже пример прямого управления радиомодулем с командами обмена данными между устройством и сервером в режиме NIDD:

Entering true direct mode.
From now on everything you type into a terminal will be transferred to the RF module as is
(and similarly in reverse direction).
NOTICE: No special commands supported here, for nothing is between you and the RF module.
YOU NEED TO REBOOT THE BOARD PHYSICALLY TO EXIT THIS MODE.

at+cereg?
+CEREG: 0,1
OK

AT+COPS?
+COPS: 0,0,MTS RUS MTS RUS,9
OK

at+cgdcont?
+CGDCONT: 1,NONIP,devkit.nidd,0.0.0.0,0,0,0,0
OK

AT+CRTDCP=1
OK

AT+CSODCP=1,16,"{'test':'hello'}"
OK

+CRTDCP:1,5,Hi hi

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

Для продвинутых пользователей открыты исходные коды прошивки, можно оценить логику работы устройства на уровне кода, внести изменения и экспериментировать. Со стороны облачной платформы доступны инструменты для обработки данных: виджеты, панели управления, инструменты Интеграции, позволяющие принять данные в любом формате в протоколах UDP, TCP и Non-IP. Инструмент Конвертер данных позволяют привести получаемый поток данных к виду понятному платформе.

DevKit и Ардуино


Несмотря на критическое отношение части профессионалов к Ардуино, которые указывают на неоптимальный код и на то, что библиотеки написаны не профессиональными разработчиками, мы изначально хотели сделать DevKit совместимым с Ардуино. Arduino IDE пользуется популярностью среди разработчиковлюбителей, а также может применяться в учебных программах ВУЗами.

DevKit полностью совместим с Ардуино R3 по своему духу, архитектуре, и разьемам. Для устройства были разработаны все сопутствующие файлы поддержки, так что оно устанавливается в Arduino IDE штатным образом.



В состав пакета для Arduino IDE включены необходимые инструменты и библиотеки, а также ряд примеров с исходными текстами. Программная совместимость с другими платами Arduino на основе STM32 позволяет использовать написанные для них библиотеки, а также загружать рабочие скетчи практически без изменений. Для программирования DevKit из Arduino IDE необходимо установить ПО STMCubeProgrammer, которое можно скачать с сайта компании STM. Наши разработчики продолжают наполнять пакет для Arduino новыми библиотеками и примерами.

В качестве простейшего примера работы с Arduino IDE рассмотрим загрузку примера Blink (мигание светодиодом). На изображении ниже можно увидеть результат загрузки и компиляции данного скетча из меню Файл Примеры 01.Basics





Поддерживаемые интегрированные среды разработки


Разработка демонстрационной прошивки производилась в интегрированной среде Em::Bitz. Программный код примера рассчитан на компиляцию с помощью GCC. Для разработки пользовательского кода пригодны любые IDE, поддерживающие семейство микроконтроллеров STM32L15x. Например, Arduino IDE, IAR Embedded Workbench, Keil uVision MDK ARM и другие.

Расширение функциональности


Функциональность можно расширять как с помощью шилдов, так и подключая любые дискретные датчики.



Установка GNSS-шилда превращает DevKit в GPS/GLONASS трекер.



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



Можно подключить специальный шилд и добавить функциональность Ethernet и карту памяти.



Подключая датчики скорости и направления ветра получаем NB-IoT метеостанцию



Подключаем ультразвуковой датчик и реле управления насосом получаем автомат контроля уровня жидкости в емкости.



В следующем материале покажем на практике, как собрать на основе NB-IoT DevKit устройство интернета вещей. Заказать NB-IoT Development Kit можно уже сейчас на нашем сайте.

Авторы:
старший менеджер группы планирования сети IoT Виталий Бачук
ведущий эксперт направления МТС Виктор Лучанский
руководитель группы планирования сети IoT Андрей Плавич
Подробнее..

Мой МТС. Продуктовая трансформация

12.04.2021 18:13:34 | Автор: admin
Всем привет! Мы продуктовая команда Мой МТС, занимаемся разработкой основного мобильного приложения компании МТС (iOS/Android) и сайта mts.ru. Месячная аудитория активных пользователей (MAU) на всех платформах свыше 23 млн. пользователей.

Данной статьей мы хотим начать цикл, посвященный трансформации нашей команды и вызванными ею изменениями. Первый пост полностью отведен под начальный этап перестройки, стартовавший с приходом внешних консультантов.

До трансформации

Погрузимся немного в исторический контекст. Изначально приложение Мой МТС разрабатывала команда внешнего поставщика. В 2016 году мы перевели продукт в In House разработку и начали планомерные работы по совершенствованию кодовой базы, команды и процессов.

На начало 2020 года команда продукта Мой МТС состояла из 63 человек, которые были организованы следующим образом:



Разработка велась по зачаточному Scrum'у с двухнедельными итерациями и основными командными ритуалами. Однако, как заметит внимательный читатель, на схеме отсутствуют scrum master'а у нас это роль, которую выполнял и продолжает выполнять кто-то из членов feature team. Также была в наличии строгая изолированность Владельцев продукта и разработчиков. Мостиком между двумя мирами служили системные аналитики и технический лидер команды. Веб-разработкой полностью занимался подрядчик. Так совпало, что начало активной фазы избавления от внешних зависимостей началось одновременно с трансформацией.

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

Как и говорилось ранее, до трансформации связи между командами разработки и бизнес направлениями не было, что давало следующие преимущества:

  • В случае появления большой срочной задачи с погонами мы могли перераспределить всех людей на эту задачу и соблюсти сроки;
  • Бэклог был единым и содержал совершенно разные задачи: с интеграционными проблемами, исключительно интерфейсные и технические, что позволяло разнопланово нагружать разработку;
  • Вариативность задач в бэклоге и единая сквозная команда аналитики помогали равномерно нагружать разработчиков мобильных платформ.


С технической точки зрения у нас имелись следующие вводные, которые хотелось бы обозначить в контексте трансформации:

  • Монолитные решения на всех платформах (iOS, Android, Web)
  • Полное отсутствие UI тестирования
  • Хаотичный процесс проверки pull request'ов без SLA


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

  • Переходите к гибким методологиям не глядя, просто примите как факт, что это верный выбор в любой компании и для любого продукта;
  • Профессионализм вашей команды не играет роли, Scrum поможет кому угодно;
  • Монолитные решения отличный фундамент для экспериментов с процессами, технический долг начнет уменьшаться на глазах с каждым спринтом.


Цели трансформации

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

Среди формальных целей руководством компании были обозначены два фактора, которые нужно было улучшить:

  • Общая прозрачность работы команды на всех уровнях понимание процессов и артефактов команды, в широком смысле этого слова, всеми сотрудниками, которым это может быть нужно, начиная с самих членов команды и заканчивая Советом директоров компании.
  • Уменьшение показателя Time-to-Market путем поиска и устранения узких мест в рабочем процессе и изменения подхода к работе в целом.


Достаточно быстро мы поняли, что для себя нам так же нужно определить и понять цели. То есть сократить T2M, чтобы что? повысить прозрачность зачем? и другие подобные вопросы. Начали обсуждать это с CPO, Владельцами продуктов и к тому времени уже прошло несколько месяцев работы в новой парадигме. Так как получилось собрать достаточно много интересной фактуры, мы собрали всю большую команду Мой МТС и рассказали, как же на самом деле команда управления продуктом видит цели и ожидаемые результаты трансформации, какие небольшие победы уже можно отпраздновать, а так же где наоборот стало хуже и что потерялось из фокуса. Вот некоторые выводы, к которым мы пришли после первого такого подхода:

  • Появилась постоянная и ритмичная поставка по направлениям.
  • Список выполняемых задач и их прогресс стал более явен как для CPO, так и для сотрудников вне команды Мой МТС.
  • У CPO высвободилось достаточно много времени, которое теперь можно уделять стратегии, видению, исследованию рынка и анализу отзывов пользователей.


С точки зрения целей трансформации, для себя мы определили, что самое главное не цифры и T2M (на начальном этапе так точно), а изменение нашего подхода к работе, мышления, и, как сказал CPO, раскачивание лодки, чтобы понимать, где она протекает. То есть сокращение Time2Market на этот период времени стало для нас не самоцелью, а процессом раскачивания устоявшейся системы с целью поиска узких мест и их разрешения. Звучит странно, но нам это помогло расставить все на свои места. Мы поняли, что:

  • Важно учиться работать в эмпирическом подходе, по HADI-циклам, вместо привычного подхода исполнительного решения поставленных сверху задач.
  • Важно до последнего искать и находить корневые причины и цели у заказчиков.
  • Важно проверять гипотезы не только в продукте и фичах, но и в процессах и рабочих подходах. Нет единственного правильного подхода к работе, постоянно нужно искать слабые места.


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

Трансформация

Трансформация затронула многие аспекты рабочего процесса в компании, но подробно хотелось бы остановиться на двух вещах планировании бэклога и формировании продуктовых команд.

Так как в МТС огромное количество продуктов, платформ, направлений и команд, в последнее время стала более очевидной необходимость стандартизировать их процессы. Например, в какой-то момент нашлись очень похожие по функционалу продукты, которые разрабатывались в разных местах и разными людьми. Чтобы избежать подобного, а также чтобы синхронизировать цели связанных продуктовых команд и повысить прозрачность постановки и достижения целей, был запущен новый процесс планирования бэклогов по кварталам.

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

Все задачи следующего квартала предварительно обсуждаются, верхнеуровнево декомпозируются, а также оцениваются командами разработки. Одним из открытий наведения порядка в планировании для нас стало понимание, что в квартале 6 Спринтов, один из которых () уходит на тех. долг (сумма 20-ти % в Спринт), второй для тестировщиков команды на релиз (сейчас релиз делается по всему приложению, релизное знамя переходит от команды к команде, но это временное явление, мы почти от этого избавились).

По итогам Квартального планирования мы получаем перечень задач, которые:

  • Обсуждены и согласованы со всеми участниками вне наших команд, например, с другими продуктами, по которым есть зависимости в реализации фичей
  • Обсуждены и предварительно проработаны командой разработки
  • Распределены по Спринтам внутри квартала
  • Презентованы всем заинтересованным лицам. В конце квартального планирования мы рассказываем о своих планах, зависимостях и рисках на встрече, где помимо остальных продуктов и команд присутствуют топ-менеджеры. Синхронизация очень масштабная в последний раз только на B2C направление было 44 продукта/платформы.

После окончания процесса Квартального планирования мы продолжаем регулярную синхронизацию по задачам на PO sync (еженедельная встреча Product Owner'ов и Chief Product Owner'а, технических лидеров, скрам-мастеров). Там же обсуждаем прогресс в достижении целей: если есть новые вводные или вскрылись не найденные ранее риски у нас есть возможность узнать об этом и повлиять как можно раньше.

Помимо Квартального планирования и PO sync, у нас в Мой МТС прижилась традиция проведения ежедневных чек-инов команды трансформации. В эту команду входят: CPO, технические лидеры, скрам-мастера. Иногда туда приглашаем и других участников, если того требует задача. Как уже говорилось, мы встречаемся этим составом ежедневно в конце рабочего дня, на 15-45 минут, обсуждаем и решаем вопросы, связанные с кадровыми изменениями, отзывами пользователей, новыми инициативами (например, перезапуск Discovery процесса, но об этом в следующих статьях), инициативами от членов команды и т.д. Крайне редко на чек-инах рассматриваются проблемы какой-то конкретной фичи, так как это более низкоуровневая повестка.

В силу размера компании нам не удалось внедрить новый подход везде и сразу, что привело к рассинхронизации при запуске нового механизма планирования у разных направления B2C, B2B и IT платформы.

Если говорить о структуре команды, то после трансформации продуктовая команда Мой МТС стала выглядеть следующим образом:



Разумеется, переход к новой структуре был поэтапным, нужно было нанять большое количество сотрудников и постепенно формировать новые команды. К сожалению, бурный рост не мог не сказаться на текучке кадров, и отток в 2020 году был самым большим за последние 4 года. Однако если рассмотреть последние месяцы 2020, когда найм по большей части был уже завершен, то ситуация заметно выправилась. Если говорить о цифрах, то в 2020 году текучка составила 30%, а в предыдущие годы (2018-2019) держалась на уровне 18%.

Переход на новую структуру, конечно же, лишь малая часть всех изменений. В целом, можно выделить следующие важные шаги:

  • Основным изменением стал переход на юниты обособленные scrum команды, состоящие из технических специалистов, дизайнера и владельца продукта.
    Юниты собираются вокруг направлений бизнеса (например, фиксированная связь, финтех и так далее). В теории, подобная трансформация должна была привести к большей вовлеченности всех участников команды в специфику своих направлений и более качественной проработке продуктовых гипотез.
  • В команде продукта появились выделенные scrum-мастера. Они выполняют важные функции:
    • коррекция процесса трансформации
    • консультирование по вопросам Agile
    • связующую функцию с корпоративным центром продуктовой культуры.
  • Выделенная команда автоматизации UI тестирования.
    Значительный рост количества команд привел быстрому развитию приложения, вместе с которым также стремительно увеличивается количество тест-кейсов в регрессе. На данный момент автоматизировано 25% основных сценариев.
  • Мы начали активно работать в направлении перехода на In House разработку WEB.
    Процесс оказался значительно сложнее, чем в случае с мобильным приложением, в силу исторического и юридического наследия. Также ожидания бизнеса не позволили замедлить или остановить разработку нового функционала.
  • В 2021 году планируем провести эксперимент по созданию гибридных команд app+web.


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

Результаты

Если формально подводить итоги трансформации, то поставленные цели были достигнуты:
1. Процесс стал прозрачным для всех
2. Time-to-market сокращен в 1,5 раза

Конечно же, существует множество нюансов, на основных из которых хотелось бы остановиться подробнее:

  • Излишняя прозрачность может быть вредной
    Применимо в случае, например, когда у стейкхолдеров есть некий технический бэкграунд (или они так думают) и они пытаются, экстраполируя свой старый опыт, активно влиять на рабочие процессы команды.Стоит отметить, что прозрачность планирования в полной мере не была достигнута. Квартальное планирование сейчас запущено параллельно на различных срезах (B2C, B2B, платформы), хотя остро стоит потребность в синхронизации.
  • Абсолютные значения показателей в вакууме
    Нам, конечно, удалось уменьшить time-to-market, но параллельно с трансформацией активно улучшались и подходы к работе владельцев продукта. Это привело к уменьшению среднего размера задачи и ускорило скорость доставки инкремента до пользователя. Даже не смотря на оговорки, подобный результат для нас очень ценен: отказ от больших и толстых задач, которые становятся неактуальными за время доставки до пользователей, является огромным плюсом. Также за прошедший год был сделан очень мощный рывок в работе с техническим долгом. Изолированные команды требуют по возможности изолированных песочниц в коде, поэтому модульность приложения стала основным техническим вектором для нас наравне с автоматизацией тестирования.


Новые проблемы

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

Также раньше мы очень большое внимание уделяли детальной проработке всех требований к фиче до старта разработки. Основные недостатки такого подхода это сужение пропускной способности всей команды и слишком тепличные условия для разработчиков и тестировщиков. В юнитах уже на первых порах стало видно, что старый подход к ТЗ не работает и нужно что-то менять аналитик не успевал готовить проработанные задачи. Для решения этой проблемы мы разделили ТЗ на две части must have для старта разработки и всё остальное. Этот подход несколько снял напряжение, но не закрыл все вопросы, поэтому дальнейшие проверки различных гипотез дело времени.

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

Планы

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

  • Вся разработка должна быть In House. На наш взгляд, это аксиома, аутсорсинг всегда непрозрачно и почти всегда неуправляемо.
  • Техническое развитие продукта
    • автоматические UI тесты для снятия лишней нагрузки с unit'ов при подготовке релизов
    • единый интеграционный backend для снижения затрат на подключения к другим системам ландшафта компании
    • дальнейшее развитие модульности приложения для упрощения работы структуры в целом. Для ускорения и стабилизации этого процесса мы планируем создать выделенную команду развития платформ.
  • Автоматизация сбора различных метрик работы unit'ов и продуктовой команды целиком.
  • Создание кросс-команды, в которую будет входить полный спектр специалистов для реализации функционала в app и web части нашего продукта.


Авторы Артем Андреев, Наталья Егорова, Алексей Кретов
Подробнее..

IoT практикум от Microsoft и МТС

23.03.2021 10:07:12 | Автор: admin

Мероприятие будет крайне полезно компаниям, перед которыми стоят задачи быстрого внедрения IoT-решений. Всего за 7 часов вы создадите полноценные IoT-решения получения и визуализации необходимой информации внутри компании.

31 марта, подробности и регистрация.

В качестве платформы для IoT-решений будет использоватьсяAzure IoT Central, куда будут передаваться данные сNB-IoT Development Kit от МТС.

Мероприятие рассчитано на технических специалистов в сферу обязанности которых входит разработка, внедрение и поддержка систем мониторинга активов компании.

К участию допускаются команды от 2 до 5 человек.
Всем командам предстоит последовательно пройти 14 челленджей (за каждый из челленджей команды получают призовые баллы):

  1. Развернуть виртуальную машину для NB-IoT шлюза

  2. Присвоить NB-IoT шлюзу публичное доменное имя с учетом названия команды

  3. Открыть порты для работы с виртуальной машиной через SSH и Node-RED

  4. Установить Node-RED

  5. Импортировать в Node-RED скелет шлюза/данных

  6. Проверить получение входных данных с NB-IoT устройства на шлюз

  7. Преобразовать данные из формата NB-IoT в JSON

  8. Развернуть приложение Azure IoT Central

  9. Развернуть Device Bridge для подключения NB-IoT шлюза к IoT Central

  10. Создать и опубликовать шаблон устройства в Azure IoT Central

  11. Проверить поступление данных в Azure IoT Central

  12. Настроить панель мониторинга в Azure IoT Central

  13. Настроить правило отправки уведомлений на почту при превышении заданных показателей

  14. Настроить экспорт данных из Azure IoT Central в хранилище двоичных данных (blob)

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

Подробности и регистрация.

Подробнее..

Who is mr. Marvin?

03.09.2020 10:04:27 | Автор: admin
В июне этого года мы выпустили на рынок умную колонку с голосовым помощником по имени Марвин. Она может работать до 2 часов без подзарядки. У колонки шесть микрофонов для обработки голосовых команд. ПО полностью разработано внутри МТС без использования сторонних коммерческих решений. В этом посте разберем основные функции и технические характеристики новинки.



Что может Марвин?


По голосовому запросу виртуальный ассистент Марвин можете отвечать на разные вопросы, позволяет слушать более 60 радиостанций, узнавать прогноз погоды, устанавливать напоминания и будильники, включать голосовые игры, узнавать о последних новостях. Для колонки можно выбрать один из трех режимов контента: 18+ полностью свободный от цензуры в отношении песен, новостей (контент доступен в исходном авторском виде), Без мата режим для взрослых, но с фильтром, блокирующим специфическую лексику, Детский установлены ограничения на выдачу контента для взрослых (песни без мата, без новостей, книги сказки).

Также колонка оборудована встроенным модулем системы Умного дома от МТС и поддерживает ZigBee- и Bluetooth Low Energy-устройства. Для подключения системы не требуется посредник-партнер, не нужны сторонние аппаратные решения. Это первая портативная колонка центр управления умным домом, который, в свою очередь, управляется голосовыми командами, и через приложение МТС Smart Нome.

Что со звуком?


Колонка оснащена цифровым сигнальным процессором для динамической аппаратной эквализации контента, который проигрывает устройство. Это обеспечивает гармоничное, красивое и качественное звучание колонки. DSP-сопроцессор позволяет управлять распределением спектральной мощности сигнала, делает звук динамически сбалансированным, управляет распределением басов. Он искусственным образом улучшает качество звучания за счет постоянного слежения за спектрограммой сигнала и формирует стереосигнал с сохранением эффектов звучания, присущих этой технологии. Такое решение позволяет сохранить качество звучания музыки и другого контента без потери качества распознавания речи.

Для гармоничного воспроизведения аудиоконтента устройство оборудовано стереодинамиками и пассивным источником низких частот. Суммарная средняя мощность звука составляет 10 Ватт.

Колонку можно подключить к любому мобильному устройству или ноутбуку с помощью Bluetooth и Airplay в качестве устройства вывода звука.


Изображение акустического пакета колонки

Про зарядку


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

ПО


Команда Центра искусственного интеллекта интегрировала в умную колонку ПО, которое позволяет активировать Марвина. Программное обеспечение обрабатывает голосовой запрос с массива микрофонов на расстоянии 4-5 метров от человека при включенном контенте, устройство может работать в шумных условиях. ПО было разработано внутри МТС специально для умного устройства без применения методов лицензирования сторонних решений. Команде разработчиков удалось создать полностью сквозное решение по обработке акустического сигнала без передачи данных третьей стороне, что позволяет одновременно управлять колонкой голосовыми командами и использовать ее в режиме Bluetooth-гарнитуры или проигрывать музыку через Airplay.

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

Начинка


Устройство состоит из трех электронных плат и обладает высокой производительностью, общая спецификация представлена в таблице:



Безопасность


Для обладателей любых умных устройств важны безопасность и конфиденциальность использования персональных данных. Умная колонка оснащена средствами шифрования всех данных, передаваемых локально и глобально, данные внутри устройства также защищены.

Кроме того, пользователи имеют возможность отключать микрофоны кнопкой на верхней панели. Устройство не передает данные в режиме реального времени, оно имеет встроенную автономную технологию ожидания активационного запроса, средства его уточнения и только после запуска этих этапов начинает формировать голосовой запрос пользователя.

Юзабельность


Запуск работы умной колонки не требует сложных манипуляций: после установки и регистрации в приложении МТС Марвин пользователь может активировать устройство. Во время активации Марвин продиктует секретный код дополнительное средство защиты при авторизации.

Умную колонку можно подключать сразу к нескольким Wi-Fi-сетям, при этом поддерживаются сети диапазонов 2.4 ГГц и 5 ГГц. При подключении к нескольким сетям активируется программный роуминг, благодаря которому колонку можно перемещать между зонами действия этих сетей устройство будет переключаться между ними автоматически. Такой функционал делает использование устройства удобным при перемещении внутри большого помещения, а также обеспечивает более стабильную работу при загруженности Wi-Fi-канала. При этом активация колонки надежно защищена, она не передает никаких данных акустического спектра в стиле dial-up-модема.

Продолжение следует


Умная колонка МТС это начало нового модельного ряда умных устройств компании. Начинка и программная разработка колонки станут основой для следующих моделей автономного мультимедийного гаджета со встроенным средством мобильной связи и голосовым помощником по имени Марвин. Так что следите за новостями и нашим блогом.

Роман Жуков, начальник отдела разработки AI-утсройств Центра искусственного интеллекта МТС.
Подробнее..

Обзор на статью Visual Transformers новый подход к тренировке моделей компьютерного зрения на основе visual tokens

24.07.2020 10:04:54 | Автор: admin
Эта работа интересна тем, что авторы в ней предлагают новый подход к тренировке моделей на изображениях использовать не только пиксели и конволюции, но ещё и представлять изображения в виде визуальных токенов и тренировать на них трансформеры. По сравнению с использованием просто архитектуры ResNet предложенный подход уменьшает MAC (multiply and accumulate operations) в 6,9 раз и увеличивает топ-1 точность на 4,53 пункта на задаче классификации ImageNet.

image


Мотивация подхода


Общепринятый подход к задачам компьютерного зрения использовать картинки как 3D array (высота, ширина, количество каналов) и применять к ним конволюции. У такого подхода есть ряд недостатков:

  • не все пиксели одинаково полезны. Например, если у нас задача классификации, то нам важнее сам объект, чем фон. Интересно, что авторы не говорят о том, что Attention уже пробуют применять в задачах компьютерного зрения;
  • Конволюции не достаточно хорошо работают с пикселями, находящимися далеко друг от друга. Есть подходы с dilated convolutions и global average pooling, но они не решают саму проблему;
  • Конволюции недостаточно эффективны в очень глубоких нейронных сетях.


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

image

  • Вначале используется обычный backbone для получения feature maps
  • Далее feature map конвертируется в визуальные токены
  • Токены подаются в трансформеры
  • Выход трансформера может использоваться для задач классификации
  • А если объединить выход трансформера с feature map, то можно получить предсказания для задач сегментации


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

Visual transformer


Теперь рассмотрим работу модели подробнее.
Как уже говорилось выше, backbone извлекает feature maps, а они передаются в слои visual transformer.
Каждый visual transformer состоит из трёх частей: токенизатор, трансформер, проектор (projector).

Токенизатор



image

Токенизатор извлекает визуальные токены. По сути мы берем feature map, делаем reshape в (H * W, C) и из этого получаем токены

image

Визуализация коэффициентов при токенах выглядит вот так:
image

Position encoding


Как обычно, трансформерам нужны не только токены, но ещё и информация об их позиции.

image

Вначале мы делаем downsample, потом домножаем на тренируемые веса и конкатенируем с токенами. Для корректировки количества каналов можно добавить 1D конволюцию.

Transformer


Наконец, сам трансформер.
image

Объединение visual tokens и feature map


Это делает projector.
image
image

Динамическая токенизация


После первого слоя трансформеров мы можем не только извлекать новые visual tokens, но и использовать извлеченные с предыдущих шагов. Для их объединения используются тренируемые веса:

image

Использование visual transformers для построения моделей компьютерного зрения


Дальше авторы рассказывают как именно применяется модель к задачам компьютерного зрения. Блоки трансформера имеют три гиперпараметра: количество каналов в feature map C, количество каналов в visual token Ct, количество visual tokens L.

Если при переходе между блоками модели количество каналов оказывается неподходящим, то используются 1D и 2D конволюции для получения необходимого количества каналов.
Для ускорения расчетов и уменьшения размера модели используют group convolutions.
Авторы в статье прикладывают **псевдокод** блоков. Полноценный код обещают выложить в будущем.

Классификация изображений


Берем ResNet и на его основе создаем visual-transformer-ResNets (VT-ResNet).
Оставляем stage 1-4, лишь вместо последней ставим visual transformers.

Выход из backbone 14 x 14 feature map, количество каналов 512 или 1024 в зависимости от глубины VT-ResNet. Из feature map создаются 8 visual tokens на 1024 канала. Выход трансформера идёт в голову для классификации.

image

Семантическая сегментация


Для этой задачи в качестве базовой модели берут panoptic feature pyramid networks (FPN).

image

В FPN конволюции работают на изображениях с высоким разрешением, поэтому модель тяжелая. Авторы заменяют эти операции на visual transformer. Опять же 8 токенов и 1024 канала.

Эксперименты


Классификация на ImageNet

Тренируют 400 эпох с RMSProp. Начинают с learning rate 0,01, в течение 5 эпох разогрева увеличивают до 0,16, а потом каждую эпоху домножают на 0,9875. Используют batch normalization и размер батча 2048. Label smoothing, AutoAugment, stochastic depth survival probability 0,9, dropout 0.2, EMA 0,99985.

Это ж сколько экспериментов пришлось прогнать, чтобы все это подобрать

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

image

image

Названия статей для сравниваемых моделей:

ResNet + CBAM Convolutional block attention module
ResNet + SE Squeeze-and-excitation networks
LR-ResNet Local relation networks for image recognition
StandAlone Stand-alone self-attention in vision models
AA-ResNet Attention augmented convolutional networks
SAN Exploring self-attention for image recognition

Ablation study


Для ускорения экспериментов брали VT-ResNet-{18, 34} и тренировали 90 эпох.

image

Использование трансформеров вместо конволюций даёт самый большой прирост. Динамическая токенизация вместо статической также дает большой прирост. Энкодинг позиции дает лишь небольшое улучшение.

Результаты сегментации


image

Как видим, метрика выросла лишь чуть-чуть, но модель потребляет в 6,5 раз меньше MAC.

Потенциальное будущее подхода


Эксперименты показали, что предложенный подход позволяет создавать более эффективные модели (в плане вычислительных затрат), которые при этом достигают лучшего качества. Предложенная архитектура успешно работает для разных задач computer vision, и можно надеяться, что её применение поможет улучшить симтемы, использующие comuter vision AR/VR, автономные автомобили и другие.

Обзор подготовил ведущий разработчик МТС Андрей Лукьяненко.
Подробнее..

Из песочницы Трассировка сервисов в мобильной транспортной сети. Как мы пришли к графовой БД Neo4j

31.08.2020 16:23:29 | Автор: admin

Часть 1. Начало


1.1 Введение и постановка задачи


В компании МТС мы централизованно занимаемся контролем качества сетей передачи данных или, проще транспортной сети (не путать с логистической транспортной сетью), далее по тексту ТС. И, в рамках нашей деятельности, нам постоянно приходиться решать две основные задачи:

  1. Обнаружена деградация клиентских (по отношению к ТС) сервисов нужно определить путь их проключения через ТС, и выяснить, является ли причиной деградации сервисов какой-либо участок ТС. Далее, будем называть это Прямой задачей.
  2. Обнаружена деградация качества транспортного канала или последовательности каналов нужно определить, какие сервисы зависят от данного канала/каналов, чтобы определить влияние. Далее, будем называть это Обратной задачей.

Под сервисами ТС понимается любое проключение клиентского оборудования. Это могут базовые станции (БС), В2В клиенты (использующие ТС МТС для организации доступа в сеть Интернет и/или наложенных сетей VPN), клиенты фиксированного доступа (т.н. ШПД), и т.д. и т.п.

В нашем распоряжении две централизованные информационные системы:
Система Performance Monitoring Данные о параметрах и топологии сети
Метрики, КПЭ ТС Параметры конфигурации, L2/L3 каналы

Любая транспортная сеть по своей сути является ориентированным графом $G=(V,E)$, в котором каждое ребро $(u,v) in E$ имеет неотрицательную пропускную способность. Потому с самого начала поиск решения указанных задач выполнялся в рамках теории графов.

Сначала вопрос сопоставления показателей качества ТС и сервисов с топологией ТС решался путем буквального объединения и представления данных топологии и качества в виде сетевого графа.

Просмотр сформированного по данным топологии и производительности графа был реализован на open source ПО Gephi. Это позволило решить задачу автоматического представления топологии, без ручной работы по её актуализации. Выглядит это так:


Здесь, узлы это, собственно узлы ТС (маршрутизаторы, коммутаторы) и базовые, рёбра каналы ТС. Цветовая маркировка, соответственно, обозначает наличие деградаций качества и статусы обработки этих деградаций.

Казалось бы вполне наглядно и можно работать, но:

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

Также, надо иметь ввиду, что в общем случае топология сети гораздо сложнее (выше приведенный фрагмент обведён красным):


И это не самый маленький сегмент есть гораздо больше и сложнее по топологии:


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



Часть 2. Автоматизация v1.0


Напоминаю, какие задачи мы решали:

  1. Определение пути проключения сервиса через ТС Прямая задача.
  2. Определение зависимых сервисов от канала ТС Обратная задача.

2.1. Транспортные сервисы для Базовых Станций (БС)


Обобщенно, организация транспорта от центрального узла (контроллера/шлюза) до БС выглядит так:


На сегментах агрегации и ядра ТС проключения выполняются через транспортные сервисы MPLS сети: L2/L3 VPN, VLL. На сегментах доступа проключения выполняются, как правило, через выделенные VLAN-ы.

Напоминаю, что у нас есть БД где лежит вся актуальная (в пределах определенного срока) параметрия и топология ТС.

2.2. Решение для коммутируемого сегмента (доступ)


Берем данные о VLAN логического интерфейса БС, и пошагово идём по связям, порты которых содержат этот Vlan ID, пока не дойдем до граничного маршрутизатора (МВН).


Для решения такой простой постановки задачи в итоге пришлось:

  1. Написать алгоритм пошаговой трассировки распространения VlanID от БС по каналам сети агрегации
  2. Учесть имеющиеся пробелы в данных. Особенно это касалось стыков между узлами на площадках.
  3. Фактически написать SPF алгоритм для того чтобы отбросить в конце тупиковые ветки, которые не ведут к МВН маршрутизатору.

Алгоритм получился из одного основного процесса и семи подпроцессов. На его реализацию и отладку было потрачено недели 3-4 чистого рабочего времени.

Кроме того, особое удовольствие нам доставили

2.2.1. SQL JOIN


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

По понятным причинам не могу здесь приводить содержимое запросов к БД, но оцените каждый уступ в тексте запроса это подключение очередной таблицы, которая нужна для, в данном случае, получения в унифицированном виде соответствия Порт VlanID:


А этот запрос для получения, в унифицированном виде кросс-коннектов VlanID внутри коммутатора:


Учитывая, что кол-во портов составляло несколько десятков тысяч, а VLAN в 10 раз больше ворочалось всё это очень нехотя. А такие запросы нужно было сделать для каждого узла и VlanID. И выгрузить всё сразу и вычислить нельзя, т.к. это последовательное вычисление пути c с пошаговыми операциями, которые зависят от результатов предыдущего шага.

2.3. Определение пути сервиса в маршрутизируемых сегментах


Здесь мы начали с одного вендора МВН, система управления которого предоставляла данные о текущем и резервном LSP через сегмент MPLS. Зная Access интерфейс, который стыковался с доступом (L2 Vlan) можно было найти LSP а затем через серию запросов к NBI системы, получить путь LSP, состоящий из маршрутизаторов и линков между ними.


  • Аналогично коммутируемому сегменту, описание выгрузки пути LSP MPLS сервиса вылилось в алгоритм с уже 17-ю подпрограммами.
  • Решение работало только на сегментах, которые обслуживались данным вендором
  • Нужно было решать определение стыков между сервисами MPLS (например, в центре сегмента был общий VPLS сервис, а от него расходились или EPIPE либо L3VPN)

Мы проработали вопрос и для других вендоров МВН, где систем управления не было, или они не предоставляли данных о текущем прохождении LSP в принципе. Решение для нескольких мы нашли, но кол-во LSP, проходящее через маршрутизатор это уже не кол-во VanID, которое прописано на коммутаторе. Затягивая такой объем данных по запросу (ведь нам нужна оперативная информация) есть риск положить железо.

Кроме этого, возникали дополнительные вопросы:

  • Сеть МВН в общем случае мультивендорная, и на одном сегменте встречаются маршрутизаторы разных производителей, управляемых разными СУ. Т.е. у нас будут данные только о куске пути MPLS сервиса.
  • СУ вендора, которая могла предоставлять данные об основном и резервном LSP, на деле прописывала и первый и второй по одному и тому же пути. Это мы видели очень часто. А нам бы хотелось знать про потенциальные пути обхода при анализе ограничений на сети.

2.4. Где и как хранить результаты. Как запрашивать данные


Полученные данные о путях проключения сервисов надо куда-то записать, чтобы потом обращаться к ним при решении наших Прямой и Обратной задач.

Вариант с хранением в реляционной БД сразу исключили: с таким трудом агрегировать данные из множества источников чтобы потом в итоге рассовать по очередным наборам таблиц? Это не наш метод. Тем более помним про многоэтажные джойны и их производительность.

Данные должны содержать информацию о структуре сервиса и зависимостях его составляющих: линках, узлах, портах и т.п.

В качестве тестового решения был выбран формат XML и Native-XML БД Exist.

Каждый сервис в результате записывался в БД в формате (подробности опущены для компактности записи):

<services><service> <id>,<description> Описание сервиса (например, наименование БС)<source> Интерфейс условной точки А<target> Интерфейс условной точки Z<<segment>> Сегменты L2/L3<topology> Информация о пути через сегмент (узлы, порты/интерфейсы, соединения)<<joints>> Стыки между сегментами (узлы, порты/интерфейсы, соединения)</service></services>

Запрос данных по прямой и обратной задачам выполнялся по протоколу XPath:


Всё. Теперь система заработала на запрос с наименованием БС возвращается топология проключения её через транспортную сеть, на запрос с наименованием узла и порта ТС возвращается список БС, которые от него зависят по подключению. Поэтому, выводы мы сделали следующие

2.5.




Вместо заголовка о выводах по части 2

2.5.1. Для коммутируемого сегмента (сети на L2 коммутаторах Ethernet)


  • Обязательно нужны полные данные о топологии и соответствии Port VlanID. Если на каком-то линке нет данных о VlanID алгоритм останавливается, путь не найден
  • Многоэтажные непроизводительные запросы к реляционной БД. При появлении нового вендора со своей спецификой параметрии добавление запросов на всех этапах работы

2.5.2. Для маршрутизируемого сегмента


  • Ограничено возможностями СУ МВН по предоставлению данных о топологии LSP MPLS сервисов.
  • Запросы конфигурации непосредственно с МВН потенциально опасны, т.к. счёт обслуживаемых LSP идет на тысячи.
  • Резервные LSP часто прописываются системой по тому же маршруту что и основные нет информации о потенциальных альтернативных путях (в том числе и помимо тех, которые держит система).

2.5.3. Общее


  • Чтобы решить, по сути, задачу в сетевом графе, мы постоянно собираем данные из табличных источников, чтобы представить их в виде графа ( визуально в голове, или в памяти программы), реализовать алгоритм, а потом разобрать обратно.
  • Алгоритмизация решений и их реализация традиционными методами требует значительных трудозатрат. На реализацию данного этапа у нас ушло в целом 3-4 месяца.
  • Масштабирование очень затруднено, т.к. любое изменение, в виде появления нового вендора либо MPLS сервиса ведёт за собой внесение изменений в структуру запросов к БД и в сам программный код.
  • Приходится писать Дейкстра подобные алгоритмы, а не использовать готовые инструменты.

2.6. Чего всё-таки хотим


  • Чтобы данные о сетевом графе ТС и хранились, и обрабатывались как сетевой граф, т.е. набор узлов и зависимостей.
  • Чтобы использовались уже готовые алгоритмы работы с графами
  • Чтобы модель данных была универсальной, а не вендорно-зависимой
  • Чтобы трассировка была возможна и на неполных данных (например, частичное отсутствие данных о VlanID)

После того как мы провели оценку возможных вариантов реализации наших хотелок определились с классом систем, которые бы всё это обеспечили из коробки это т.н. графовые базы данных.

Хоть и читается последнее предложение как нечто линейное и простое, учитывая что ранее с таким классом БД никому из нас (и наших айтишников, как потом выяснилось тоже) сталкиваться не приходилось к решению пришли в некоторой степени случайно: подобные базы данных упоминались (но не разбирались) в обзорном курсе по Big Data. В частности, там упоминался продукт Neo4j. Мало того, что он, судя по описанию, удовлетворял всем нашим требованиям, у него ещё есть полностью бесплатная функциональная community-версия. Т.е. не 30-дневный триал, не обрезанный основной функционал, а полностью рабочий продукт, который можно не спеша изучить. Не последнюю (если не основную) роль в выборе сыграла широкая поддержка графовых алгоритмов.



Часть 3. Пример реализации прямой задачи в Neo4j


Чтобы не затягивать линейное повествование о том, как реализуется модель ТС в графовой БД Neo4j сразу покажем конечный результат на примере.

3.1. Трассировка пути проключения интерфейса Iub для БС 3G



Путь проключения сервиса проходит по двум сегментам маршрутизируемому МВН, и коммутируемому РРЛ (радиорелейные станции работают как Ethernet-коммутаторы). Путь через РРЛ сегмент определяется также, как было описано в части 2 по прохождению VlanID интерфейса БС по сегменту РРЛ до граничного маршрутизатора МВН. Сегмент МВН соединяет граничный (с сегментом РРЛ) маршрутизатор с маршрутизатором к которому подключен контроллер БС (RNC).

Изначально, из параметрии Iub, мы знаем точно какой МВН является шлюзом для БС (граничный МВН), и каким контроллером обслуживается БС.

Исходя из этих начальных условий, построим 2 запроса к БД для каждого из сегментов. Все запросы к БД строятся на языке Cypher. Чтобы сейчас не отвлекаться на его описание, воспринимайте его просто как SQL для графов.

3.1.1. Сегмент РРЛ. Путь по VlanID


Cypher-запрос трассировки пути сервиса по имеющимся данным о VlanID и топологии L2:
Фрагмент Cypher-запроса
(конструкция WITH передача результатов одного этапа запроса на следующий (конвейеризация обработки) )
Промежуточные результаты запроса (визуальное представление в консоли Neo4j Neo4j Browser)
Получение узлов БС и МВН между которыми будет проводиться поиск пути сервиса Iub

match (bts:node {name:'BTS_29_ХХХХ_N}), (mbh:node {name:'MBH_29_YYYYY_N})with bts, mbh

Получение узлов Vlan БС интерфейса Iub

match (bts)-[:port_attach]->(:port)-[:vlan]->(vlan:vlan) with bts as bts,  vlan.vlanid AS vlan_bts   , mbh 

Выбираем узлы ТС на той же площадке с БС, на портах которых прописан VlanID Iub БС
MATCH  ((bts)-->(pl_bts:PL)-->(n:node)-[:port_attach]->(pid:port)-->(v:vlan)) where (v.vlanid=vlan_bts and v.updated > bts.updated - 864000000) with distinct(v) as v,n,mbh,vlan_bts, bts

по алгоритму Дейкстра находим кратчайший путь от VlanID ТС узла площадки БС до граничного МВН
CALL apoc.algo.dijkstra(v, mbh, 'port_attach>|port_hosted>|<node_vlan|v_ptp_vlan>|ptp_vlan>|located_at>|to_node>', 'weight',10000000000.0,1) YIELD path as path_pl_mbh

Из цепочки Vlan получаем список узлов, портов, и связей между портами, который, в итоге, и будет являться путём проключения сервиса Iub от БС до граничного маршрутизатора
WITH FILTER(node in nodes(path_pl_mbh) WHERE  (node:vlan)) as vlans_node , path_pl_mbh, bts ,mbh , vlan_btsunwind vlans_node as vlan_nodematch (vlan_node)-->(p1:port)match p=(p1)-[:port_hosted|to_port|v_to_port|to_node|located_at]->()return p, bts, mbh

Результат:


Как видно, путь получен, даже несмотря на частичный недостаток данных. В данном случае отсутствует информация о стыке порта БС с портом радиорелейной станции.

3.1.2. Сегмент РРЛ. Путь по L2 топологии


Допустим, попытка в п. 3.1.1. не удалась по причине полного или частичного отсутствия данных о параметрии VlanID. Другими словами подобная непрерывная цепочка, доходящая до узла МВН не выстраивается:

Тогда можно попробовать определить проключение сервиса как кратчайший путь до МВН по топологии L2:
match (bts:node {name:'BTS_29_ХХХХ_N}), (mbh:node {name:'MBH_29_YYYYY_N})with bts, mbhCALL apoc.algo.dijkstra(bts, mbh, 'located_at>|to_node>|to_port>|v_to_port>|port_hosted>|port_attach>', 'weight',1.0,1) YIELD path as preturn p

Результат:


Как видно, получен такой же результат. Здесь недостаток информации о стыке БС с РРС восполнен прохождением связи через объект (узел) площадки, на которой они находятся. Разумеется, точность такого метода будет меньше, т.к. в общем случае Vlan может быть прописан не по кратчайшему пути, предполагаемому алгоритмом Дейкстра. Зато запрос состоит из всего двух операций.

3.1.3 Сегмент МВН. Трассировка пути от граничного МВН до контроллера


Здесь так же используем алгоритм Дейкстра.
Один путь с минимальной стоимостью
match (mbh:node {name:MBH_29_XXX}), (rnc:node {name:RNC_YYY})CALL apoc.algo.dijkstra(mbh,rnc, 'port_attach>|port_hosted>|<node_vlan|ptp_vlan>|located_at>|to_node>|to_port_mbh>', 'weight',10000000000.0,1) YIELD path as pathreturn path

Топ-2 пути с минимальной стоимостью (основной + альтернатива)
match (mbh:node {name:MBH_29_XXX}), (rnc:node {name:RNC_YYY})CALL apoc.algo.dijkstra(mbh,rnc, 'port_attach>|port_hosted>|<node_vlan|ptp_vlan>|located_at>|to_node>|to_port_mbh>', 'weight',10000000000.0,2) YIELD path as pathreturn path

Топ-3 пути с минимальной стоимостью (основной + две альтернативы)
match (mbh:node {name:MBH_29_XXX}), (rnc:node {name:RNC_YYY})CALL apoc.algo.dijkstra(mbh,rnc, 'port_attach>|port_hosted>|<node_vlan|ptp_vlan>|located_at>|to_node>|to_port_mbh>', 'weight',10000000000.0,3) YIELD path as pathreturn path


Аналогично в данном случае отсутствует информация о непосредственных стыках МВН с RNC. Но это не мешает построить путь сервиса, пусть и предполагаемый алгоритмом (об этом позже).

3.2. Трудозатраты


Реализация Прямой задачи, показанная сейчас, разительно отличается от подхода разработай алгоритм, программу, способ хранения и извлечения результатов здесь всё сводится к напиши запрос к БД. Забегая вперёд, отметим, что весь цикл от разработки простой модели графа, загрузки данных в Neo4j из реляционной БД, написания запросов, и до получения результата занял, в общей сложности, один день.

3-4 месяца vs 1 день!!! Это было последним доводом для окончательного ухода в графовую БД.



Часть 4. Графовая БД Neо4j и загрузка данных в неё


4.1. Сравнение реляционных и графовых БД


Сравнительная характеристика Реляционная БД Графовая БД
Хранение данных Данные хранятся в наборе отдельных таблиц, связи между строками которых могут быть определены по ключевым полям через специальные отношения: один к одному, один ко многим, многие ко многим.

Данные хранятся или в виде узлов или в виде отношений (направленных связей/ссылок между узлами). И у тех и у других может быть произвольный набор параметров.

Структура данных Тот, кто строит запросы к БД, должен точно знать структуру хранения данных, и какие связи между данными, помимо определенных через внешние ключи, могут быть. Любые изменения/дополнения в структуре данных требуется соотносить с моделью хранения, при этом заранее оценивая последствия для производительности БД в целом. По этой причине коммерческие системы, использующие для хранения РБД, берут с клиентов деньги за адаптацию потребностей последних к своей модели хранения данных
Структура данных (узлов и взаимосвязей между ними) определяется самими данными. Пользователю доступна вся информация о текущей структуре. Отсутствует жесткая фиксированная схема возможно одновременное существование нескольких вариантов представления данных. Прямое и универсальное моделирование данных пользователем. Любой объект может быть представлен набором из трех сущностей: Узел, Связь, Параметры.
Проблема JOIN Не всегда поля, по которым понадобится сделать объединение данных при запросе индексированы. Это может значительно снизить быстродействие запроса, т.к. заставляет планировщик прибегать к NESTED-LOOP
Связи между узлами определяются на этапе загрузки в БД или на этапах постпроцессинга (вычисления связей). Если угодно ГБД это как если бы в РБД все нужные JOIN уже были сделаны, причем на уровне отдельных полей отдельных строк.
JOIN chain Чем больше мы сцепляем JOIN операций друг за другом в одном запросе тем больше падение производительности. Т.е. мы экспоненциально теряем в производительности на каждый вложенный JOIN в запросе. В данной статье приведен пример решения задачи поиска в глубину запросами к РБД Oracle, и к ГБД Neo4j:

Проблемы не существует. Обход графа в глубину нативное свойство ГБД.
Зависимость от кол-ва записей/размера БД Чем больше записей в объединяемых таблицах, тем большее время требуется от РБД для обработки запроса, даже если количество реально возвращаемых записей неизменно
Запрос отсекает именно ту часть графа, которая связана с интересующими узлами/связями и работает только с ней, при этом размер БД графа может быть любым. Например, запрос идет от узла МВН-Х, при этом всего в графе может быть как 1000 так и 1 млн узлов МВН поиск всё равно будет внутри сегмента графа, включающего только МВН-Х.


4.2. Модель данных


Базовая модель представления ТС до уровня L3 топологии включительно:


Разумеется, модель обширнее представленной, и содержит также и MPLS сервисы, и виртуальные интерфейсы, но для упрощения рассмотрим её ограниченный фрагмент.

В такой модели связь между двумя сетевыми элементами одного региона может быть представлена как:


4.3. Загрузка данных


Загрузку данных выполняем из БД параметрии и топологии ТС. Для загрузки в Neo4j из SQL БД используется библиотеки APOC apoc.load.jdbc, которая принимает на вход строку подключения к RDBMS и текст SQL запроса, и возвращает множество строк, которые через CYHPER выражения отображаются на узлы, связи, или параметры. Такие операции выполняются слой за слоем для каждого типа объектов модели.

Например, проход для загрузки/обновления узлов, представляющих сетевые элементы (Nodes):
with "jdbc:oracle:thin:usr /passw@IP:1521/db" as url // DB connection stringCALL apoc.load.jdbc(url," select distinct mr,region_code,site_code,node, nodeip,TYPE,VENDOR, coalesce(updated, trunc(localtimestamp-7)) as updatedfrom (    select distinct mr,region_code,site_code,node, nodeip,TYPE,VENDOR, updated from GRAPH_IPMPLS_NE    union    select distinct mr,region_code,site_code,node, nodeip,TYPE,VENDOR, updated from GRAPH_RRN_NE    union    select distinct mr,region_code,site_code,node, nodeip,TYPE,VENDOR, updated from GRAPH_CONTROLLERS_NE) twhere mr is not null and region_code is not null and site_code is not null ") YIELD row

Вызов процедуры apoc.load.jdbc,
получение набора данных
match (reg:Region {region_code:row.REGION_CODE})-->(pl:PL {SiteCode:row.SITE_CODE}) with pl, row, {updated:row.UPDATED, weight:1000000000000} as conn_params

Для каждой строки из набора данных
по коду региона и сайта ищутся узлы
представляющие соответствующие площадки
merge (pl)<-[loc:located_at]-(n:node {ip:row.NODEIP})merge (pl)-[to_n:to_node]->(n)set n.name=row.NODEset n.region_code = row.REGION_CODEset n.type = row.TYPEset n.updated = row.UPDATEDset n.vendor = row.VENDORset loc += conn_paramsset to_n += conn_params

Для каждого объекта площадки обновляются
связанные с ней сетевые элементы (node).
Используется инструкция MERGE + SET,
которая обновляет параметры объекта,
если он уже существует в БД, если нет
то создает объект. Тут же записываются
параметры узла Node и его связей с узлом PL

И так далее по всем уровням модели ТС.

Поле Updated используется при контроле актуальности данных в графе не обновляемые дольше определенного периода объекты удаляются.



Часть 5. Решаем обратную задачу в Neo4j


Когда мы только начинали, выражение трассировка сервиса в первую очередь вызывало следующие ассоциации:


Т.е., что трассируется непосредственно текущий путь прохождения сервиса, в данный момент времени.

Это не совсем то, что мы имеем в графовой БД. В ГБД трассируется сервис по взаимосвязям объектов, определяющих его конфигурацию в каждом задействованном сетевом элементе. Т.е., в виде графовой модели представляется конфигурация, и результирующая трасса это проход по модели, представляющей эту конфигурацию.

Так как, в отличие от коммутируемого сегмента, фактические маршруты сервиса в сегменте mpls определяются динамическими протоколами, нам пришлось принять некоторые

5.1. Допущения для маршрутизируемых сегментов


Т.к. из данных конфигурации mpls сервисов нет возможности определить их точный путь прохождения через сегменты, управляемые динамическими протоколами маршрутизации (тем более, если используется Traffic Engineering) для решения используется алгоритм Дейкстры.
Да, есть системы управления, которые могут по NBI-интерфейсу предоставлять актуальный путь сервисных LSP, но пока у нас такой вендор только один, а вендоров на сегменте МВН больше чем один.

Да, есть системы анализа протоколов маршрутизации внутри AS, которые, слушая обмен IGP протоколов, могут определить текущий маршрут интересующего префикса. Но стоят такие системы как сбитый Боинг, а учитывая что такую систему нужно развернуть на всех AS того же мобильного бэкхола стоимость решения вместе со всеми лицензиями составит стоимость Боинга, сбитого чугунным мостом, привязанным к ракете Ангара при полной заправке. И это ещё при том что подобными системами не вполне решены задачи учета маршрутов через несколько AS c использованием BGP.

Поэтому пока так. Конечно, мы добавили несколько подпорок в условия стандартного алгоритма Дейкстра:

  • Учёт статуса интерфейсов/портов. Отключенный линк повышается в стоимости и идет в конец возможных вариантов пути.
  • Учёт резервного статуса линка. По данным системы Performance Monitoring вычисляется присутствие в mpls канала только трафика keepalive, соответственно, стоимость такого канала также увеличивается.

5.2. Как решить обратную задачу в Neo4j


Напоминание. Обратная задача получение списка сервисов, зависимых от конкретного канала или узла транспортной сети (ТС).

5.2.1. Коммутируемый L2 сегмент


Для коммутируемого сегмента, где путь сервиса и конфигурация сервиса это практически одно и то же, задачу ещё можно решить через CYPHER-запросы. Например, для радиолерейного пролета из результатов решения Прямой задачи в п 3.1.1., сделаем запрос от модема радиорелейного линка развернем все цепочки Vlan, которые проходят через него:

match (tn:node {name:'RRN_29_XXXX_1'})-->(tn_port:port {name:'Modem-1'})-->(tn_vlan:vlan)with tn, tn_vlan, tn_portcall apoc.path.spanningTree(tn_vlan,{relationshipFilter:"ptp_vlan>|v_ptp_vlan>", maxLevel:20}) yield path as ppwith tn_vlan,pp,nodes(pp)[-1] as last_node, tn_portmatch (last_node)-[:vlan]->(:port)-->(n:node)return pp, n, tn_port

Красным узлом обозначен модем, Vlan которого разворачиваем. Обведены 3 БС на которые в итоге вывело развертывание транзитных Vlan с Modem1.


У такого подхода есть несколько проблем:

  • Для портов должны быть известны и загружены в модель сконфигурированные Vlan.
  • Из-за возможного фрагментирования, цепочка Vlan не всегда выводит на терминальный узел
  • Невозможно определить относится ли последний узел в цепочке Vlan к терминальному узлу или сервис, на самом деле, продолжается дальше.

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

5.2.2. Маршрутизируемый сегмент


С маршрутизируемым сегментом, как уже описано в п 5.1, выбирать не приходится для решения обратной задачи на основании данных текущей конфигурации какого-то промежуточного линка MPLS никаких средств нет конфигурация не определяет в явном виде трассу сервиса.

5.3. Решение


Решение было принято следующее.

  • Проводится полная загрузка модели ТС, включая БС и контроллеры
  • Для всех БС выполняется решение прямой задачи трассировка сервисов Iub, S1 от БС до граничного МВН, а затем от граничного МВН до соответствующих контроллеров или шлюзов.
  • Результаты трассировки записываются в обычную SQL БД в формате: Наименование БС массив элементов пути сервиса

Соответственно, при обращении к БД с уловием Узел ТС или Узел ТС + Порт, возвращается список сервисов (БС), в массиве пути которых есть нужный Узел или Узел+Порт.





Часть 6. Результаты и выводы


6.1. Результаты


В итоге система работает следующим образом:


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


Для получения списка сервисов, зависимых от узлов или каналов ТС (решение обратной задачи) разработан API для внешних систем (в частности Remedy).

6.2. Выводы


  • Оба решения подняли на качественно новый уровень автоматизацию анализа качества сервисов и транспортной сети.
  • Кроме этого, при наличии готовых данных о трассах сервисов БС, стало возможно быстро предоставлять данные для бизнес-подразделений о технической возможности включения В2В клиентов на конкретных площадках по емкости и качеству трассы.
  • Neo4j показал себя как очень мощный инструмент для решения задач с сетевыми графами. Решение отлично документировано, имеет широкую поддержку в различных сообществах разработчиков, постоянно развивается и улучшается.

6.3. Планы


В планах у нас:

  • расширение технологических сегментов, моделируемых в БД Neo4j
  • разработка и внедрение алгоритмов трассировки сервисов ШПД
  • увеличение производительности серверной платформы

Спасибо за внимание!
Подробнее..

ИСТОРИЯ ОДНОЙ ПОКУПКИ В ИНТЕРНЕТ-МАГИЗИНЕ МТС ИЛИ КАДР РЕШАЮТ ВСЕ

15.02.2021 20:10:51 | Автор: admin

Я решил написать эту историю по мотивам своего опыта покупки подарка на день Святого Валентина в интернет-магазине МТС. Моему кошельку эту стало, гораздо меньше, чем моим нервам. Я потратил меньше 10 тысяч рублей, если бы я тогда знал, как это все повернется, плюнул бы на эти 8 тысяч и не стал бы ввязываться. Может быть кто-то, прочитав ее, сэкономит себе немного нервов и не станет рисковать, связываясь с МТС.

ЭКСПОЗИЦИЯ

Формально я живу в Москве, но по факту территория Москвы за МКАДом территорией Москвы можно назвать только с большой натяжкой и не только по причине транспортной доступности, хотя в первую очередь именно поэтому. В общем каждую свою вылазку в Москву в период эпидемии Ковид я планирую заранее, а если есть возможность остаться дома, остаюсь дома.

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

Утром 13 февраля я забрал клавиатуру, зашел съесть что-то в фудкорт у метро Таганская. Пока ел свой суп и ковырялся в видео обзорах в youtube, пришла мне в голову идея. Ведь завтра день Святого Валентина, а не купить ли мне новые классные беспроводные наушники. Повыбираю, покручу, поверчу и подарок классный будет. И вот что было дальше.

СЦЕНА ПЕРВАЯ

Насмотревшись видео обзоров я остановился на наушниках Jabra Elite 65t. Поковырялся в поисках подходящего продавца. Обычно, когда я выбираю между ИП РогаКопытов и каким-то солидным брендом, я выбираю солидный бренд, на случай возможных проблем с покупкой. МТС всегда в моих глазах был, если не премиум брендом, то чем-то вроде этого. Есть Билайн, Мегафон, а теперь и Теле2, а есть МТС. Смотрю наличие и цены и нахожу искомые наушники в интернет-магазине МТС. Цена самая низкая, есть в наличии в 2 салонах, на сайте заявлена возможность возврата товара в течение 7 дней. Все просто идеально. Сейчас закажу, поеду и сразу заберу, - радостно думаю я. Сделал заказ, пришла СМС с подтверждением. На всякий случай звоню в телефонную поддержку МТС +7 800 250-05-05, чтобы убедится, что уже можно ехать в салон.

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

- Здравствуйте, это МТС, меня зовут Анжелика, как я могу к Вам обращаться?

- Здравствуйте, меня зовут Руслан. Я недавно сделал заказ, звоню чтобы убедиться, что уже можно ехать забирать.

- Заказ привязан к номеру телефона, с которого Вы звоните?

- Да, там должны быть беспроводные наушники.

(проходит несколько секунд)

- Заказ готов к выдаче по адресу: г. Москва, ул. Профсоюзная, 56, можете ехать забирать.

- Спасибо.

Все так складно, хорошо работает МТС, думаю я по дороге к метро. Кругом огромные сугробы, дорога очень скользкая, ехал очень долго. Наконец добрался до салона. Называю молодому человеку в салоне МТС номер заказа и код подтверждения. Он ковыряется в компьютере, а потом заявляет:

- Наушников в наличии нет, такие наушники вчера приносили в связи с браком. Мы их отправили на склад, это был последний экземпляр.

- Как же так, ведь я сделал заказ, потом звонил убедиться, что можно забирать по телефону Вашей поддержки?

- Не знаю, мне никто не звонил. Вашего заказа нет.

- Как Вы так работаете? Я специально приехал сюда за своим заказом. Такая работа интернет-магазина МТС катастрофа. На Митинском радиорынке сервис лучше!

- Согласен с Вами, ничем не могу Вам помочь.

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

- Здравствуйте, я сделал заказ в Вашем интернет-магазине, приехал его забрать в салон, а мне тут говорят, что товара нет.

(проходит несколько минут, я слушаю музыку в трубке)

- Приносим извинения за доставленные неудобства. Единственное, что могу Вам предложить это оформить заказ в другом салоне в ТЦ Хорошо. Я уже позвонил туда, товар на месте, можно сразу поехать и забрать.

- Я уже сейчас могу поехать туда?

- Да, можно забрать прямо сейчас.

- Хорошо, оформляйте.

СЦЕНА ВТОРАЯ

Выхожу на улицу по дороге прокладывая маршрут. ТЦ Хорошо, где мне оформили заказа находится рядом с метро Полежаевская. Приходит очередная СМСка с подтверждением заказа. Добрался до ТЦ Хорошо. Погода отличная, ветра почти нет. Идет небольшой снег, новое здание ТЦ Хорошо выглядит очень эффектно. Захожу внутрь, на входе охрана в деловых костюмах, тепловизор. Полы вылизаны, кругом все в стекле и мраморе. Нашел салон МТС, захожу внутрь, народу почти никого. Вежливый парень за стойкой быстро находит мой заказ и приносит его со склада. Уже через пару минут меня просят приложить карту к терминалу. Я уже немного устал, в теплом салоне с вежливыми сотрудниками, окруженный всей этой красотой потерял бдительность и не потребовал проверки товара перед оплатой. Это была моя вторая ошибка. Пока парень заканчивал оформление я засомневался. Когда мне отдали коробку с наушниками я решил проверить их на месте. Открываю коробку, достаю наушники, пытаюсь включить. Нажимаю кнопку, задерживаю 1, 2, 3.. 15, реакции никакой. Может быть разрядились, - думаю я. Попросил разрешить воспользоваться розеткой в салоне. Пока поставил на зарядку, открываю мануал. Все как обычно, задержать на несколько секунд, загорится синий светодиод. Через 10 минут снова безуспешно пытаюсь включить наушники.

- Что-то не получается? Не можете включить?

- Что-то не работают.

Сначала пытались включить наушники вместе с парнем. В итоге он сдался и зовет помощь зала. Другая сотрудница салона (видимо старшая смены) велит подать наушники ей. Я не возражаю, хотя уже тогда был уверен, что наушники просто неисправны. Проходит еще минут 15 тупняка. И вот я слышу волшебную фразу в лучших традициях ритейл торговли. А посмотрите вот эти классные наушники Honor AirBuds Magic. У меня у самой такие, вообще супер. Старо как мир, но все еще работает. Смотрю на коробку наушников. Все гламурно, а ля Airpods. Время вечер, ну не уезжать же ни с чем, - думаю я, - Давайте возьму эти. Забираю коробку и еду домой.

СЦЕНА ТРЕТЬЯ

Приехал вечером довольный, показываю всем купленные наушники. А жена мне и говорит:

- Так для спортзала такие в ушах держаться не будут.

- Ну, да не будут. Ты бы знала, как все было сложно.

- (про себя думаю) М-да. Эх, ну завтра обменяю на другие.

Звоню утром 14 февраля в поддержку:

- Я вчера по ошибке купил не те наушники, могу я их сдать назад?

- Вы можете сдать товар назад в течение 7 дней после покупки при условии сохранения товарного вида и комплектации.

- Отлично, а могу я сдать их в другом салоне МТС?

- Нет, сдать товар вы можете только в том же месте, где приобретали.

- Придется снова совершить вояж из Некрасовки в Хорошево-Мневники - с досадой думаю я. - Спасибо.

Проверил все еще раз и снова поехал в ТЦ Хорошо. Захожу в салон МТС, моих прежних знакомых продавцов уже нет, весь состав сменился. Подошел к продавцу в спортивной куртке МТС больше похожей на спортивную куртку члена сборной по вольной борьбе.

- Чем могу Вам помочь?

- Я вчера по ошибке купил наушники, хочу их сдать.

Парень советуется с коллегами, другой парень в костюмных брюках, рубашке и галстуке, видимо старший в салоне, говорит: Товар серийный, возврат можно сделать только через рекламацию, мы должны составить заявление, сделать фотографии. Это займет некоторое время, Вам придется подождать. Меня передали для оформления девушке с длинными ногтями. Она долго строчила что-то на клавиатуре. Меня попросили достать паспорт. Достал. Прошло минут 15. Уже начинаю нервничать. Паспорт достал, а никто его не берет. Пытаюсь как-то привлечь внимание. Девушка дает заявление, я его заполняю. Опять строчит на клавиатуре, проходит еще минут 15.

- Девушка, вы со мной закончили? Паспорт мой Вам не нужен?

- Нет, не нужен. Я еще не закончила.

- Я правильно понимаю, что сейчас вы сделаете куда-то запрос, потом нужно будет дождаться ответа и только потом я смогу вернуть товар?

- Да, все правильно.

- Но ответ же будет сегодня?

Тут они все как-то замялись. Наверное сегодня, а может и нет.

- Так вы тут без меня можете закончить, я пока погуляю по ТЦ? А есть какой-то предельный срок для рассмотрения этих заявок?

- Срок 3 дня, но обычно быстрее.

- Давайте я наушники у Вас оставлю, чтобы не таскать с собой.

- Наушники оставить нельзя.

Девушка мне говорить примерно то, что написано в объявление в гардеробе: Администрация за оставленные вещи ответственности не несет.

- Вы же магазин, почему вы не можете у себя их положить?

- Нам запрещено.

- Странно. Ну ладно, возьму с собой.

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

- Ответа пока нет, Мы с Вами свяжемся.

- Но прошло уже 2 часа, вы может узнаете у них, сколько еще ждать.

- Я только что узнавал, еще не готово.

- Так у вас написано на сайте, что до 2 часов.

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

- Я знаю, что в законе написано, только вы у МТС лучше, чем это предусмотрено законом о защите прав потребителей. Зачем Вы мне сейчас про это говорите? У меня складывается ощущение, что вы просто так технично хотите меня отбрить!

- Нет, что Вы! Заявка еще не рассмотрена просто. Возврат предусмотрен, но нужно дождаться ответа.

- Что же Вы мне сразу не сказали, что сегодня вероятнее всего ответа еще не будет? Я бы не ждал у моря погоды.

- У нас есть Ваш номер телефона, мы с вами свяжемся.

Настрочил в Твиттере в @ru_mts. Сказали, что передали коллегам, что со мной свяжутся.

TwitterTwitter

ЗАКЛЮЧИТЕЛЬНАЯ СЦЕНА

Наступает утро 15 февраля. Поверяю СМС, Твиттер. Ничего нет, никто не звонил. Звоню сам.

- Меня зовут Светлана, как я могу к вам обращаться?

- Меня зовут Руслан, я позавчера купил наушники (рассказываю все подробно).

- Узнайте, пожалуйста, что с моей заявкой на возврат.

Девушка с ходу мне отвечает, - Для возврата товара Вам необходимо обратиться в салон.

- Вы слышали, что я вам сейчас рассказал?! Я же говорю, что вчера уже был в салоне, оставлял заявку на возврат. Узнайте что с ней.

- (недовольным голосом) Подождите, я свяжусь с салоном.

(проходит несколько минут, в трубке играет музыка)

- Я связалась с салоном. Ваша заявка была некорректно оформлена. Поэтому Вам надо еще раз обратиться в салон.

- Вы мне предлагаете еще раз поехать через всю Москву, чтобы просто оставить новую заявку?!

- Мне так сказали в салоне.

- Вот же уроды - думаю я и вешаю трубку.

Снова написал @ru_mts. И вот приходит мне наконец тот ответ, который подразумевался. Осмелились мне это сказать только через Твиттер @ru_mts, никто из салона мне так и не позвонил.

Вот что написал мне @ru_mts:

twitter2twitter2twitter3twitter3

А ведь товар вскрыла в салоне сотрудница МТС, чтобы проверить, что наушники работают!

МОРАЛЬ ИСТОРИИ

Сначала безалаберные сотрудники МТС гоняли меня по салонам, чтобы забрать интернет-заказ. Потом долго втирали мне очки с возвратом. В итоге все равно отказали. Потратили кучу моих нервов и времени. Сейчас мне больше, чем зря потраченных денег жалко того времени, которое я потратил, чтобы достучаться до МТС. МТС самостоятельно взяла на себя обязательства по возврату лучше, чем предусмотрено законом. Взяла их только, чтобы повесить себе на флаг? Не собиралась их выполнять с самого начала? Допускаю, что если пойти на принцип, если потратить кучу нервов, времени и денег, то можно заставить МТС оформить обещанный возврат. Но нужна ли такая возможность такой ценой? Некомпетентные сотрудники по телефону и в салоне вызывают раздражение и создают необоснованные ожидания. Ведь старший менеджер, осмотрев товар в салоне, мог бы сразу сказать мне, что в случае, когда товар вскрыт вероятность положительного решения по возврату близка к нулю, чтобы я не чувствовал себя обманутым лохом. Наверное, там процентов с продаж не предусмотрено, ведь можно было бы мне предложить мне обмен. Он получил бы свой бонус к зарплате, а я не упражнялся бы тут в писательстве. Пока я был в салоне мне встретились только трудовые мигранты, которые на плохом русском просили пополнить счет телефона или выяснить условия работы денежных переводов. Реклама на прилавке салона очень хорошо иллюстрирует приоритеты компании.

реклама на прилавке в салоне МТС в ТЦ Хорошореклама на прилавке в салоне МТС в ТЦ Хорошо

Видимо основной бизнес салонов МТС превратился в банальные обменники для переводов в Узбекистан и Киргизию. Ретейл торговля мобильниками и аксессуарами сечйчас выглядит как побочный бизнес, чтобы было чем заполнить пространство салона.

Когда Чичваркин продал Евросеть, фирма стала потихоньку умирать. Я тогда думал, что же случилось, ведь внешне кроме собственника ничего не поменялось? Но что-то точно произошло. У меня салон Евросети был через дорогу, я часто там покупал всякое. Было время я даже ходил туда заряжать телефон.

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

Была ли мотивация и квалификация в компании МТС? Я не знаю, раньше мне не доводилось быть их клиентом. Сейчас я точно могу сказать, что ни квалификации, ни мотивации у сотрудников МТС нет. Компания сделала безграмотную круглосуточную телефонную поддержку, набрала туда людей по объявлению с фиксированной зарплатой, нисколько не заинтересованных в развитии компании.

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

ВСЕ-ТАКИ КАДР РЕШАЮТ ВСЕ.

Подробнее..

Не те игрушки как мы научили нейросеть бороться с порно в стримах

13.08.2020 14:10:01 | Автор: admin
Всем привет, меня зовут Олег, я занимаюсь компьютерным зрением в команде Видеоаналитики МТС и сегодня расскажу вам, как мы защищаем от небезопасного контента стриминговую платформу WASD.tv, в частности про детектирование порнографии в постановке задачи action recognition.




Наш кейс это стриминговый сайт для геймеров, киберспортсменов и любителей живых трансляций формата Twitch.tv. Одни пользователи транслируют развлекательный контент, а другие его смотрят. Контент может быть самый разный: игры, живая музыка, интерактивы, мукбанг, ASMR, готовка, подкасты, прочее и в принципе не ограничен ничем, кроме воображения стримера.

И правил платформы, за соблюдением которых следят модераторы.


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

Когда перед нами встала задача отслеживания небезопасного контента, сразу стало очевидно, что отличить безопасный контент от небезопасного не так-то просто. Первое, что было важно понять порно и нагота не тождественные понятия.

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

Нагота это необязательно про NSFW: сумо, борьба, одетые люди в латексе всё это безопасный контент, на котором открытые решения зачастую отрабатывают некорректно.

Исходя из этих соображений, мы начали смотреть, как можно решить эту задачу. Из интересных открытых решений уже несколько лет существует обученная на закрытых данных модель Open NSFW от Yahoo (имплементация на TF). Ещё есть классный открытый репозиторий Александра Кима nsfw data scraper, из которого можно получить несколько сотен тысяч изображений с реддита, imgur и вроде бы каких-то других сайтов. Изображения разбиты на пять классов: порно, хентай, эротика, нейтральный и рисунки. На основе этих данных появилось много моделей, например раз, два
Опенсорсные решения страдают от нескольких проблем в целом невысокое качество некоторых моделей, некорректное срабатывание на вышеупомянутых сложных кейсах и безопасных изображениях вроде тверкающих девушек и мемов с Рикардо Милосом, а также проблематичность доработки, потому что либо модели устаревшие и обучены на закрытых данных, либо данные очень шумные и с непредсказуемым распределением.



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

Распознавание действий


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

Как вообще решают эту задачу? В восемнадцатом году вышёл отличный обзор от qure.ai, и кажется, что с тех пор радикального прогресса в области не произошло, так что рекомендую. Более интересный ресерч на тему видео перешёл в более сложную задачу понимания и пересказа видео. Там и графовые сетки, и self-supervised learning этому даже был полностью посвящен второй день на последнем Machines Can See.

Так вот, классификация действий. История прогресса в нейросетевых моделях примерно следующая: сначала проводили обучение трехмерных сверточных сетей с нуля (С3D), затем стали пробовать свёртки с какой-нибудь рекуррентной архитектурой или механизмом внимания; в какой-то момент Андрей Карпатый предложил разными способами мержить представления с разных кадров, еще позже стандартом стало делать двуглавые модели, где на один вход подается последовательность кадров в BGR/RGB, а на другой посчитанный на них плотный оптический поток. Еще были приколы с использованием дополнительных признаков и специальных слоёв вроде NetVLAD. В итоге мы смотрели на модели, лучше всего показавшие себя на бенчмарке UCF101, где видео разбиты по 101 классу действий. Такой моделью оказалась архитектура I3D от DeepMind, она зашла лучше всего и у нас, поэтому расскажу о ней подробнее.

DeepMind I3D


Как бейзлайны мы пробовали обучать C3D и CNN-LSTM обе модели долго обучаются и медленно сходятся. Затем мы взяли I3D, и жизнь стала лучше. Это две трёхмерные сверточные сети для BGR и оптического потока, но есть особенность в отличие от предыдущих моделей, эта предобучена на ImageNet и собственном датасете от Deepmind Kinetics-700, в котором 650 тысяч клипов и 700 классов. Это обеспечивает крайне быструю сходимость модели в несколько часов к хорошему качеству.

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

Мы подаем в модель 16 кадров, а не 64. Раньше у нас был квадратный вход, но, учитывая специфику платформы, мы поменяли соотношение сторон входа на 16:9. Задача бинарная классификация, где нулевой класс это не порно, а единичный порно. Обучали с помощью SGD с моментумом, он показал себя чуть лучше Адама. Аугментации минимальные горизонтальные флипы и JPEG-компрессия. Тут ничего особенного.

Завершая тему моделей после I3D еще выходили модели EVANet Neural Architecture Search для последовательности кадров, SlowFast Networks сеть с двумя каналами с разным фреймрейтом, и статья Google AI Temporal Cycle-Consistency Learning , но мы их не исследовали.

На чём обучали-то?


Как я уже писал выше, с данными туго. Никто их публиковать не хочет, это сложно с юридической и этической точек зрения начиная от лицензий и заканчивая согласием каждого причастного к контенту лица. Датасеты, их лицензии и публикация это вообще весело. Если кто-то хочет написать об этом статью, я с удовольствием почитаю. Из значимых академических датасетов есть только бразильский NPDI, и он, к сожалению, маленький по объему, его распределение данных недостаточно разнообразно, он состоит из ключевых кадров, и процедура его получения не самая простая. А мы ведь еще и датасет из видео хотим! Пришлось собирать самостоятельно.

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

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

Второй подход это ручная сборка. Ее плюсы заключаются в том, что мы можем моделировать любое желаемое распределение данных, данные более предсказуемы, и их проще размечать просто потому, что их меньше. Но есть и минусы. Очевидно, данных при таком подходе получается меньше, и помимо этого они могут страдать от biasа сборщиков, так как он моделирует распределение и может что-то упустить.
Мы выбрали второй подход. Составили список того, что потенциально могло бы оказаться на стриминговой платформе: самые разные игры, анимация, аниме, игра на музыкальных инструментах, реакции, мемы, хайлайты стримов и попытались покрыть самые разные возможные типы небезопасного контента от чего-то обычного до трэша в духе порно с птеродактилями. Отдельно упомянули компьютерные игры, по которым часто делают 3д-хентай Overwatch, например. И начали собирать. В итоге могу выделить два инсайта.

Фетишисты неплохие сборщики данных


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

Да и ютуберы тоже


Пример раз: на ютубе есть компиляции хайлайтов стримеров, иногда они покрывают отдельный год, длятся часами и содержат под тысячу монтажных склеек, т.е. сцен. Пример два: топы игр/аниме/сериалов. Скажем, вам надо внятно объяснить нейросети, что такое аниме. При этом в Японии огромное количество студий, стиль которых прогрессирует с каждым годом. Решение скачать видео с топами аниме за отдельные годы от известного ютубера. Или вам нужно покрыть разнообразие сцен из популярной игры. Идете и качаете ролик например videogamedunkey по этой игре.

Итерации данных


У нас было несколько итераций данных. Сначала это было около ста видео хронометражом около 70 часов с наивной разметкой все кадры с порносайтов порно, всё с ютуба непорно, из которых мы более-менее равномерно сэмплировали последовательности кадров для датасета.

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

В итоге честно разметили данные, и эти ошибки пропали. В контексте скрапинга возникает мысль, что если при ручном отборе видео закралась такая ошибка, как с черными экранами, то при скрапинге тысяч роликов ее было бы еще сложнее отследить.

Как размечали почти для всех роликов использовали инструмент от OpenCV CVAT.

Пять копеек про CVAT
Расшифровывается как Computer Vision Annotation Tool. Разрабатывается в Нижнем Новгороде. Запускается в докере, можно сделать свою мини-Толоку. Проблема он предназначен для сегментации и детекции, но не для классификации. Пришлось парсить их XML. Потом написали для разметчика свой простенький инструмент.


Затем мы в ходе работы собрали ещё видео, обновили каталог игр, и в итоге сейчас у нас есть несколько сотен часов видео по нескольким десятками разных категорий, и мы знаем, что они состоят из ~30000 уникальных сцен, плюс данные со звездочкой, о которых мы поговорим чуть ниже.

Отлично, у нас есть сырые размеченные данные! Как нам из них получить хороший датасет? Ролики разной длины, для каждой категории собраны видео разного хронометража и степени разнообразия как это всё связать воедино? Сколько сэмплов мы можем взять из датасета? Его разнообразие как-то фундаментально ограничено (как максимум количеством кадров видео), как нам понять, что мы берем лишнего?

В начале работы мы не особо заморачивались над этими вопросами и просто брали из каждого видео отдельного класса столько сэмплов, чтобы порно и непорно в датасете было примерно поровну, а количество сэмплов определялось интуитивно (ну вроде бы несколько раз в минуту почти во всех видео что-то радикально разное происходит, будем брать 10000 сэмплов), а затем эмпирически по метрикам обученных моделей.

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

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

Давайте будем искать монтажные склейки

Можно было использовать просто пики нормы разности соседних кадров, но мы использовали открытую сеть специально для нахождения монтажных склеек TransNet. Это дало нам два результата: первый что мы узнали, сколько у нас в принципе сцен в данных, а второй что мы узнали, какие категории данных имеют более низкое разнообразие. Докачали хентая, майнкрафта и прочего.

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

Собрали датасет из 20000 сэмплов в трейне, 2000 в валидации и 2000 в тесте, обучили модель, нам понравились метрики на тесте, отправили в продакшн.

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

Это и есть данные со звездочкой. Они позволили нам заточиться на разнообразный контент платформы и снизить нагрузку на модераторов. Теперь в основном ложные срабатывания происходят на новых играх так, мы одно время чаще ловили Death Stranding и Valorant.

Текущий датасет состоит из 30000/5000/3000 сэмплов train/val/test.

Эволюция наших метрик на нашем тесте, разбитым по категориям, и сравнение с открытыми решениями (кликабельно)


В качестве метрики мы используем f1-меру с подвохом. Мы стараемся делать так, чтобы precision наших моделей стремился к единице, и в таком случае f1-мера становится прокси полноты.



Благодаря нашим детекторам время проверки всей платформы модераторами снижается в несколько раз. Помимо порнографии мы отлавливаем наготу, логотипы телеканалов и спортивные трансляции, но это истории для другого раза.

Fin.



Видеоверсию материала можно увидеть здесь
Подробнее..

Контроль соблюдения контракта API ограничения или возможности

30.12.2020 20:10:58 | Автор: admin
Из этой статьи вы узнаете, какие преимущества предоставляет контроль контракта API, что можно и нужно контролировать и как организовать процедуры контроля для исключения негативного влияния на производство.

Когда в 1825 году Англия первыми из всех запустила железнодорожное сообщение между городами, мир еще жил по солнечному времени, ориентируясь на полдень момент верхней кульминации солнца. Фактическая разница во времени между городами в одной географической полосе могла достигать 30 минут. Отсутствовала синхронизация.

Поезд, который отправлялся из Лондона в 12:00 по местному времени и должен был прибыть в Бристоль в 13:00, по местному времени прибывал в 13:30. Для местных жителей и пассажиров поезда это не было критичным явлением, но для компании-перевозчика, которая строит бизнес вокруг расписаний, планировать работу с каждым новым маршрутом становилось дорогим удовольствием. К стандартным проблемам, как опоздания, сбои в работе или аварии, прибавилась еще одна каждый новый маршрут кратно увеличивал затраты на перевозку.

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

Переведём эту историю на язык ИТ и получим, что сопровождение интеграционных стыков, каждый из которых требует уникального подхода, приводит к кратному удорожанию продукта. И цена продукта будет расти с каждой новой интеграцией. Если для одного продукта (условного поезда) это не так заметно, то для компании с десятками подключаемых модулей (условного перевозчика) это серьезная нагрузка на бюджет.

Каждый разработчик API знает, что такое обратная совместимость, что контракт необходимо соблюдать и что в этот контракт включить, чтобы он был ожидаем потребителем. Но представьте вы учли все Best Practices, подробно расписали суть сервиса, добились соответствия сервиса контракту API, но сроки интеграции при этом не сократились, а затраты на интеграцию остались прежними.

Попробуем разобраться.

Но сперва договоримся о терминах. В рамках текущего материала контрактом API обозначается любая цифровая информация (цифровой артефакт), который описывает программный интерфейс, его поведение и изменения во времени. Такой артефакт, в зависимости от решаемой задачи, называется API Documentation, API Specification, API Definition, API Agreements или API Reference. Однако мы, чтобы упростить картину восприятия интеграционного домена и систематизировать знания, объединим их в один термин контракт API.

Под интеграцией подразумевается процесс или состояние стыка двух и более программных продуктов.

Сервис означает исполняемый модуль, предоставляющий точку для удаленного вызова (SOAP, REST и т.д.)

Ниже речь идет об HTTP API, но концепция применима и к другим типам.

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

Начнем

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



Другими словами, цифровой продукт это цепочка интеграций из множества разных протоколов и, соответственно, типов API REST, RPC, SOAP и т.д. Все узлы цепи, в свою очередь, отдельные продукты со своими возможностями. А каждый узел это история: продукта, интеграции, кода.



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

Какая бы история ни была, без описания API она не произойдет.

С другой стороны, если история продукта привела к описанию оригинального контракта API, отличающегося от неких общепринятых индустриальных стандартов, вы получаете долгую и мучительную интеграцию. Усилий на подключение необходимо прикладывать больше.

Очевидно, что, если описание контракта понятное, полностью соответствует поведению сервиса и для него существует множество программных инструментов, количество потребителей будет расти. В таком случае время жизни сервиса ограничено только временем жизни технологии (например, SOAP).



Приведу пример описания API в OpenAPI спецификации (исходный текст: swagger.io/docs/specification/describing-request-body).



Что определяет соответствие контракта вашего API некоему стандарту? Каковы критерии соответствия контракта API этому стандарту? Достаточно ли описать сервис в OpenAPI спецификации или в GraphQL и считать, что задача выполнена?

Как и в любой задаче с неизвестными, определим ключевые объекты предметной области и события. Для этого обозначим ключевой объект API, участников интеграции, их действия и инструменты, которые обеспечивают их действия.

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

Регулятором является тот, кто согласует возможность интеграции: информационная безопасность, корпоративная архитектура, отдел качества, юристы и прочие службы контроля. Участник с каждой стороны выполняет некоторый набор операций, чтобы началась передача данных по каналу интеграции. Но первое действие в любой интеграции это заявление потребителя о наличии сервиса с удаленной точкой вызова. Это заявление владелец может передать через полноценный цифровой контракт, или от руки на бумажной салфетке.



Но вне зависимости от способа описания и используемого стандарта, суть содержимого контракта API всегда одна и включает три категории информации:

  • ЧТО предоставляется (данные, функции, ресурсы);
  • КАК предоставляется (условия использования);
  • ГДЕ предоставляется (расположение).


В общем, как и с любым договором купли-продажи товара.

Если погружаться в детали, состав контракта API можно разделить на множество категорий:
1. Атрибуты и их описание именование, типизация (например, в зависимости от семантики);
2. Версионирование, обратная совместимость;
3. Условия доступности авторизация, квоты, гранулярность, монетизация.

В зависимости от типа ваших потребителей к вашей интеграции предъявляется разный набор требований со стороны регулятора и потребителя.

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



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

Когда вы предоставляете API партнерам, он становится лицом вашего программного продукта. Подключение партнера всегда более чувствительный процесс, чем интеграция двух продуктов внутри одной компании. Даже если на стороне партнера такой же разработчик, как и вы, их внутренние правила производства, культура и предметная область могут сильно отличаться от вашей. На этом уровне появляются требования бизнес-модели продукта к интеграции (например, не более 1 млн запросов бесплатно), добавляется строгий контроль качества, юридический контроль и контроль информационной безопасности.

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

Рассмотрим подробнее интеграцию как последовательный процесс, а также каким образом в этом процессе участвует контракт API.

Если глобально, интеграция состоит из трех этапов: подготовка, согласование и управление.



Первый этап все виды операций владельца API и потребителя, которые в итоге запустят процедуру интеграции.

Как Владелец я обязан описать сервис, сообщить или выложить его на ресурс и заявить, что к моему продукту имеется точка доступа. Все действия, начиная с момента я решил предоставлять API до заявил о наличии сервиса.

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

На этом этапе контракт API закрывает потребность Владельца как быстрее объяснить возможности сервиса и потребность Потребителя получить подробную информацию о возможности сервиса и подключиться.

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

Как Регулятор от контроля качества (QA), я должен подтвердить соответствие уровня доступности сервиса (SLA) моим требованиям. Например, если сервис приема платежей будет доступен только 50% времени, тогда только каждый второй платеж будет доходить по назначению, что в итоге может привести не только к потере репутации компании.

Как Регулятор от корпоративной архитектуры (Enterprise Architect), я должен подтвердить, что модели данных публичных сервисов идентичны. Например, если выводится еще один сервис работы с платежами, но наименование атрибутов запроса-ответа отличается от предыдущего, потребителю придется реализовать mapping параметров для работы с обоими сервисами одновременно.

Как Регулятор от информационной безопасности, я должен проверить наличие чувствительной информации в сервисе. Например, если он возвращает персональные данные, но выставлен за обычным TLS каналом, то компания может получить серьезный штраф за нарушение законов Российской Федерации (ФЗ-152).

Контракт, как описание API может и должен описывать каждую деталь в зависимости от потребности Регулятора. Эту информацию он будет искать в любом случае и подтверждать, но ее наличие в контракте кратно сокращает сроки согласования.

По факту согласования интеграции происходит получение доступа к сервису и первый вызов.

Третий этап управление потреблением.

Хотя подключение состоялось и задача решена, у каждого участника все еще возникают вопросы, и ответить на них может только контракт API.

Как Владелец API, я хочу понять, к какой версии сервиса подключен партнер Х, а к какому Y, чтобы определить условия потребления у этих сервисов и могу ли я их изменить.

Как Потребитель API, я хочу понимать свои права в случае нарушения SLA.

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

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



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

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



В ином случае, если описание API содержит необходимую информацию, соответствует общим стандартам, под него выпущено множество инструментов, его поддерживают внутренние или внешние регламенты, затраты существенно сокращаются.



Вывод: стандарт необходим для унификации действий участников интеграции и сокращения их затрат. Соответствие контракта API стандарту определяется не используемым технологиям, но и по возможности унификации вне зависимости от его семантики. Чем больше работ удастся унифицировать за счет оцифровки, тем выше шанс автоматизации.

Предположим, мы осознали, что не только команда партнера хочет знать, что у вас вписано в контракте API, а еще информационная безопасность и контроль качества. Добившись типизации их работ, мы сократили сроки интеграции. Но как как определить, какие данные важны участникам и что именно ускорит процесс интеграции?

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



Владелец сервиса (бизнес-владелец): хочу, чтобы партнер нажатием кнопки в своем приложении мог вызвать такси;

Информационная безопасность: персональные данные только в определенно защищенном канале;

Контроль качества: доступность сервиса должна соответствовать заявленному уровню.

Как это выглядит. Рассмотрим сервис в виде пирамиды Маслоу, где каждый слой выполняет свою задачу. На нижнем уровне находится железо, сети, виртуализация все, что отвечает за физическую (и немного программную) среду передачи данных. Этот слой определяет ширину канала и общую физическую пропускную способность. Нижний уровень фиксируется в контракте, как обязательство придерживаться ширины канала, типа шифрования, адреса хостов.

Выше инфраструктуры архитектурный компонент продукта (исполняемый код). Этот уровень объясняет, как организовано хранение данных и какие технологии взаимодействия компонентов. Информация с него обычно указывается в соглашении в виде разрешено выполнять не более 100 вызовов в минуту или вызовы полностью логируются.

Следом архитектура модели данных, или предметная область продукта. Здесь уже история про семантику сервиса, типизацию атрибутов, коды ошибок, версионирование и обратную совместимость, авторизацию. Этот уровень обычно полностью вписывается в контракт, объясняет схему запроса и ответа, технические условия подключения.

На вершине пирамиды формируется бизнес ценность чтобы нажал кнопку, и приехало такси. Но и этот уровень обычно описывается в соглашении к сервису как описание бизнес-модели.

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

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



Еще раз взглянем на процесс интеграции. Все требования к сервису в итоге выливаются в операции по их подтверждению.

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



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

Но как подтвердить, что контракт содержит необходимые данные и что сервис соответствует контракту, чтобы доверять ему?

Решение простое, как в истории с железнодорожным временем, но внедрение скорее будет крайне сложным.



Определяете необходимый состав контракта API, встраиваете его наполнение в процессы производства, контролируете соответствие контракта необходимой схеме в design time, и контролируете поведения сервиса на соответствие контракту в run time.

Разберем контроль контракта на примере OpenAPI спецификации (для подхода CodeFirst) в DesignTime:

1. Допустим у вас есть репозиторий с описанием корпоративной модели данных:
a. В нем указано, что все методы работы с платежами содержат в имени ресурса pay, а все атрибуты, оперирующие номером счета, имеют строковый тип длиной ровно 10 символов и называются pay_number.
b. Для всех методов работы с платежами уровень доступности не менее 99%.
c. Определенным паттернам входных/выходных данных соответствует категория данных по ИБ и определенные категории могут быть доступны только за своими каналами. Например, набор из паспортных данных и ФИО однозначно определяется как персональные и могут быть доступны только за ГОСТ TLS.
d. К методам, которые возвращают скоринговую информацию, необходима расширенная авторизация по атрибутам партнера и обязательно проверка баланса при вызовы, т.к. потребление платное. Так же здесь же можно указать допустимый rate limit и т.д.
2. В процессе производства, в зависимости от названия методов и указанных переменных, в спецификацию добавляются необходимые разделы, описывающие схему авторизации, уровень доступности, категория данных;
3. На выходе получаете описанный API, который содержит необходимую информацию о потоке данных, способах авторизации и уровнях доступности. И каждый раздел контракта можно проверить и провалидировать автоматически.

Пример категоризации метода через extensions в OpenAPI


И контроль поведения сервиса контракту в режиме RunTime:
1. Организуете инфраструктуру, которая содержит элементы API Gateway, Microgateway, Observability
2. При выводе сервиса на ИТ-ландшафт, в зависимости от категории данных в аннотации, сервис прописывается за соответствующими хостами
3. В момент потребления
a. схема данных в транзакции сверяется со схемой в контракте
b. определяется уровень доступности сервиса
c. определяется интенсивность потребления сервиса
d. определяются свойства потребителя
4. И в случае несоответствия требованиям контракта, сервис будет доступен или не доступен для потребления с описанием причины

Пример валидации схемы запроса, на соответствие схеме контракта


На базе указанных операций управляется доступность сервиса валиден или недоступен в потреблении или не доступен на витрине для подключения.



Как итог, от контроля контракта и соответствия сервиса контракту вы получаете:
1. Сокращение времени и затрат на интеграцию (всех участников);
2. Сокращение затрат на поддержку сервиса;
3. Масштабирование потребителей без увеличения стоимости продукта;
4. Источник монетизации продукта.

В случае несоблюдения контракта затраты и ошибки будут расти с каждой новой интеграцией.
Подробнее..
Категории: Api , Блог компании мтс , Мтс

OpenTelemetry на практике

18.01.2021 16:06:50 | Автор: admin
Совсем недавно два стандарта OpenTracing и OpenCensus окончательно объединились в один. Появился новый стандарт распределенного трейсинга и мониторинга OpenTelemetry. Но несмотря на то, что разработка библиотек идет полным ходом, реального опыта его использования пока не слишком много.

Илья Казначеев, который занимается разработкой восемь лет и работает backend-разработчиком в МТС, готов поделиться тем, как применять OpenTelemetry в Golang-проектах. На конференции Golang Live 2020 он рассказал о том, как настроить использование нового стандарта для трейсинга и мониторинга и подружить его с уже существующей в проекте инфраструктурой.



OpenTelemetry стандарт, который появился относительно недавно: в конце прошлого года. При этом он получил широкое распространение и поддержку множества вендоров ПО для трейсинга и мониторинга.

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



Для трейсинга и мониторинга существует множество вендорских решений. До недавнего времени было два открытых стандарта: OpenTracing от CNCF, который появился в 2016, и Open Census от Google, появившийся в 2018.

Это два довольно неплохих стандарта, которые конкурировали между собой некоторое время, пока в 2019 году они не решили объединиться в один новый стандарт, который называется OpenTelemetry.



Этот стандарт включает в себя распределенный трейсинг и мониторинг. Он совместим с первыми двумя. Более того, OpenTracing и Open Census прекращают поддержку в течение двух лет, что неотвратимо приближает нас к переходу на OpenTelemetry.

Сценарии использования

Стандарт предполагает широкие возможности совмещения всего со всем и является по сути активной прослойкой между источниками метрик и трейсов и их потребителями.
Давайте взглянем на основные сценарии.

Для распределенного трейсинга можно напрямую настроить подключение к Jaeger или к тому сервису, который вы используете.



Если трейсинг транслируется напрямую, можно использовать config и просто заменить библиотеку.

В случае, если ваше приложение уже использует OpenTracing, можно воспользоваться OpenTracing Bridge оберткой, которая будет конвертировать запросы к OpenTracing API в OpenTelemetry API на верхнем уровне.



Для сбора метрик также можно настроить прямой доступ в Prometheus к порту для сбора метрик вашего приложения.



Это пригодится, если у вас простая инфраструктура, и вы собираете метрики напрямую. Но стандарт предоставляет и более гибкие возможности.

Основной сценарий использования стандарта это сбор метрик и трейсов через коллектор, который также запускается отдельным приложением либо контейнером в вашу инфраструктуру. Кроме того, можно взять готовый контейнер и установить его у себя.

Для этого достаточно настроить в приложении экспортер в формате OTLP. Это grpc-схема для передачи данных в формате OpenTracing. Со стороны коллектора можно настроить формат и параметры экспорта метрик и трейсов конечным потребителям, либо в другие форматы. Например, в OpenCensus.



Коллектор позволяет подключать большое количество видов источников данных и множество приемников данных на выходе.



Таким образом, стандарт OpenTelemetry обеспечивает совместимость с многими открытыми и вендорскими стандартами.

Стандартный коллектор расширяем. Поэтому у большинства вендоров уже готовы экспортеры в их собственные решения, если они есть. Вы можете использовать OpenTelemetry, даже если применяете сбор метрик и трейсов от какого-то закрытого вендора. Таким образом решается проблема с vendor lock-in. Даже если что-то еще не появилось непосредственно для OpenTelemetry, это можно пробросить через OpenCensus.

Сам коллектор очень просто конфигурируется через банальный YAML конфиг:



Здесь указываются ресиверы. В вашем приложении может быть какой-то другой источник (Kafka и т.д.):



Экспортеры получатели данных.
Процессоры методы обработки данных внутри коллектора:



И pipelines, которые непосредственно определяют, как будет обрабатываться каждый поток данных, который протекает внутри коллектора:



Давайте рассмотрим один показательный пример.



Допустим, у вас есть некий микросервис, к которому вы уже прикрутили OpenTelemetry и настроили его. И еще один сервис с аналогичной фрагментацией.

Пока все легко. Но появляются:

  • legacy-сервисы, которые работают через OpenCensus;
  • база данных, которая отдает данные в своем формате (например, напрямую в Prometheus, как это делает PostgreSQL);
  • еще какой-то сервис, работающий в контейнере и отдающий метрики в своем формате. Вам не хочется перебилдить этот контейнер и прикручивать sidecars, чтобы они переформатировали метрики. Вы хотите просто брать и отправлять их.
  • железо, с которого вы тоже собираете метрики и хотите как-то использовать их.


Все эти метрики можно объединить одним коллектором.



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

Теперь мы хотим использовать эту информацию. В качестве экспортера трейсов можно указать Jaeger, а метрики отправлять в Prometheus, или что-то совместимое. Допустим, всеми любимую VictoriaMetrics.

Но что, если мы вдруг решили переехать в AWS и использовать местный трейсер XRay? Не проблема. Это можно пробросить через OpenCensus, в котором есть экспортер для XRay.

Таким образом, из этих кусков можно собрать всю вашу инфраструктуру для метрик и трейсов.

С теорией покончено. Поговорим о том, как использовать трейсинг на практике.

Инструментация Golang приложения: трейсинг

Сначала нужно создать корневой span, от которого и будет расти дерево вызовов.

ctx := context.Background()
tr := global.Tracer(github.com/me/otel-demo)
ctx, span := tr.Start(ctx, root)
span.AddEvent(ctx, I am a root span!)
doSomeAction(ctx, 12345)
span.End()

Здесь указывается название вашего сервиса или библиотеки. В трейсе таким образом можно определить spans, которые лежат именно в рамках вашего приложения, и те, которые пошли в импортированные библиотеки.

Дальше создается корневой span с указанием названия:


ctx, span := tr.Start(ctx, root)


Выбирайте название, которое будет внятно описывать уровень трейса. Например, это может быть либо название метода (или класса и метода), либо слой архитектуры. Например, инфраструктурный уровень, уровень логики, уровень баз данных и т.д.

Данные о span также кладутся в контекст:


ctx, span := tr.Start(ctx, root)
span.AddEvent(ctx, I am a root span!)
doSomeAction(ctx, 12345)


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

ctx, span := tr.Start(ctx, root)
span.AddEvent(ctx, I am a root span!)
doSomeAction(ctx, 12345)
span.End()

Так наш span выглядит в Jaeger:



Его можно развернуть и посмотреть логи и атрибуты.

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

func doSomeAction(ctx context.Context, requestID string) {
span := trace.SpanFromContext(ctx)
span.AddEvent(ctx, I am the same span!)

}
Обратите внимание, что закрывать здесь его не нужно, потому что он закроется в том же методе, где был создан. Мы просто берем его из контекста.

Записываем сообщение в корневой span:



Иногда нужно создать новый дочерний span, чтобы он существовал отдельно.

func doSomeAction(ctx context.Context, requestID string) {
ctx, span := global.Tracer(github.com/me/otel-demo).
Start(ctx, child)
defer span.End()
span.AddEvent(ctx, I am a child span!)

}

Здесь мы получаем глобальный трейсер по имени библиотеки. Этот вызов можно обернуть в какой-нибудь метод, либо использовать глобальную переменную, потому что во всем вашем сервисе он будет одинаков.

Дальше создается дочерний span из контекста, и ему присваивается имя по аналогии с тем, как мы делали это в начале:


Start(ctx, child)


Не забудьте, что span нужно закрыть в конце метода, в котором он был создан.


ctx, span := global.Tracer(github.com/me/otel-demo).
Start(ctx, child)
defer span.End()


Пишем в него сообщения, которые попадают в дочерний span.



Здесь видно, что сообщения отображаются иерархически, и дочерний span находится под родительским. Он ожидаемо короче, потому что это был синхронный вызов.

В нем показываются атрибуты, которые можно писать в span:

func doSomeAction(ctx context.Context, requestID string) {

span.SetAttributes(label.String(request.id, requestID))
span.AddEvent(ctx, request validation ok)
span.AddEvent(ctx, entities loaded, label.Int64(count, 123))
span.SetStatus(codes.Error, insertion error)
}

Например, сюда попал наш request. id:



Можно добавлять events:


span.AddEvent(ctx, request validation ok)


Кроме того, сюда можно добавлять label. Это работает примерно также, как структурный лог в виде logrus:


span.AddEvent(ctx, entities loaded, label.Int64(count, 123))


Здесь мы видим свое сообщение в логе span. Можно развернуть его и посмотреть labels. В нашем случае сюда добавился label count:



Потом это будет удобно использовать при фильтрации в поиске.

Если возникла ошибка, в span можно дописать статус. В этом случае он будет помечен как ошибочный.


span.SetStatus(codes.Error, insertion error)


Раньше стандарт использовал коды ошибок из OpenCensus, и они были из grpc. Сейчас оставили только OK, ERROR и UNSET. OK ставится по умолчанию, ERROR в случае ошибки добавляете вы.

Здесь видно, что трейс ошибки помечен красным значком. Есть код ошибки и сообщение о ней:



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

Трейсинг микросервисов

В OpenTelemetry уже есть множество set party реализаций interceptors и middleware для различных фреймворков и библиотек. Их можно найти в репозитории: github.com/open-telemetry/opentelemetry-go-contrib

Список фреймворков, для которых есть interceptors и middleware:

  • beego
  • go-restful
  • gin
  • gocql
  • mux
  • echo
  • http
  • grpc
  • sarama
  • memcache
  • mongo
  • macaron


Как это использовать, посмотрим на примере стандартного http клиента и сервера.

middleware client

В клиенте просто добавляем interceptor в качестве транспорта, после чего наши запросы обогащаются на trace.id и необходимую для продолжения трейса информацию.

client := http.Client{
Transport: otelhttp.NewTransport(http.DefaultTransport),
}
req, _ := http.NewRequestWithContext(ctx, GET, url, nil)
resp, err := client.Do(req)

middleware server

На сервере добавляется небольшой middleware с названием библиотеки:

http.Handle("/", otelhttp.NewHandler(
http.HandlerFunc(get), root))
err := http.ListenAndServe(addr, nil)

Дальше как обычно: получаете span из контекста, работаете с ним, пишите в него что-то, создаете дочерние spans, закрываете их и т.д.

Так выглядит простой запрос, проходящий через три сервиса:



На скриншоте видна иерархия вызовов, разделение на сервисы, их длительность, последовательность. На каждый из них можно кликнуть и посмотреть более подробную информацию.

А так выглядит ошибка:



Легко отследить, где она произошла, когда и сколько времени прошло.
В span можно посмотреть подробную информацию о контексте, в котором произошла ошибка:



Более того, поля, которые относятся ко всему span (различные id запроса, ключевые поля в таблице в запросе, еще какие-то мета данные, которые вы хотите положить) можно вкладывать в span при его создании. Грубо говоря, не нужно копипастить все эти поля в каждое место, где вы обрабатываете ошибку. Можно записать данные о ней в span.

middleware func

Вот небольшой бонус: как сделать middleware, чтобы можно было использовать его в качестве глобального middleware для таких вещей как Gorilla и Gin:

middleware := func(h http.Handler) http.Handler {
return otelhttp.NewHandler(h, root)
}

Инструментация Golang приложения: мониторинг

Пришло время поговорить о мониторинге.

Подключение к системе мониторинга настраивается аналогично тому, что делается для трейсинга.

Измерения делятся на два типа:

1. Синхронные, когда пользователь явно передает значения в момент вызова:
  • Counter
  • UpDownCounter
  • ValueRecorder


int64, float64

2. Асинхронные, которые SDK считывает в момент коллекта данных из приложения:
  • SumObserver
  • UpDownSumObserver
  • ValueObserver


int64, float64

Сами метрики бывают:

Аддитивные и монотонные (Counter, SumObserver), которые суммируют положительные числа, и они не уменьшаются.

Аддитивные, но не монотонные (UpDownCounter, UpDownSumObserver), которые могут суммировать положительные и отрицательные числа.

Неаддитивные (ValueRecorder, ValueObserver), которые просто записывают последовательность значений. Например, какое-то распределение.

В начале программы создается глобальный измеритель, которому указывается название библиотеки или сервиса.

meter := global.Meter(github.com/ilyakaznacheev/otel-demo)
floatCounter := metric.Must(meter).NewFloat64Counter(
float_counter,
metric.WithDescription(Cumulative float counter),
).Bind(label.String(label_a, some label))
defer floatCounter.Unbind()

Дальше создается метрика:


floatCounter := metric.Must(meter).NewFloat64Counter(
float_counter,
metric.WithDescription(Cumulative float counter),
).Bind(label.String(label_a, some label))


Ей указывается название:


float_counter,


Описание:


metric.WithDescription(Cumulative float counter),


Набор лейблов, по которым вы потом можете фильтровать запросы. Например, при построении дашбордов в Grafana:


).Bind(label.String(label_a, some label))


В конце программы также нужно вызвать Unbind для каждой метрики, что освободит ресурсы и правильно ее закроет:


defer floatCounter.Unbind()


Записывать изменения просто:

var (
counter metric.BoundFloat64Counter
udCounter metric.BoundFloat64UpDownCounter
valueRecorder metric.BoundFloat64ValueRecorder
)

counter.Add(ctx, 1.5)
udCounter.Add(ctx, -2.5)
valueRecorder.Record(ctx, 3.5)

Это положительные числа для Counter, любые числа для UpDownCounter, которые он будет суммировать, и также любые числа для ValueRecorder. Для всех видов инструментов в Go поддерживаются int64 и float64.

Вот что мы получаем на выходе:

# HELP float_counter Cumulative float counter
# TYPE float_counter counter
float_counter{label_a=some label} 20

Это наша метрика с комментарием и заданным лейблом. Потом можно ее взять либо напрямую через Prometheus, либо экспортировать через OpenTelemetry коллектор, и дальше использовать там, где нам нужно.

Инструментация Golang приложения: библиотеки

Последнее, о чем хочется сказать это возможность, которую стандарт дает для инструментирования библиотек.

Раньше, когда использовались OpenCensus и OpenTracing, вы не могли инструментировать ваши отдельные библиотеки, особенно опенсорсные. Потому что в этом случае у вас получался vendor lock-in. Тот, кто плотно работал с трейсингом, наверняка обращал внимание на то, что большие клиентские библиотеки, или крупные API к облачным сервисам, время от времени падают с трудно объяснимыми ошибками.

Тут бы очень пригодился трейсинг. Особенно в продуктиве, когда у вас происходит какая-то неясная ситуация, и очень хотелось бы знать, почему она произошла. Но все, что у вас есть это сообщение об ошибке из вашей импортированной библиотеки.

OpenTelemetry решает эту проблему.



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

Не нужно заботиться о vendor lock-in, не нужно переживать по поводу того, как будет использована эта информация и будет ли использована вообще. Библиотеки и приложения инструментируются заранее, а конфигурация экспорта данных указывается при инициализации приложения.

Таким образом видно, что настройки конфигурации задаются в SDK приложении. Дальше нужно заняться экспортерами трейсинга и метрик. Это может быть один экспортер через OTLP, если вы экспортируете в OpenTelemetry коллектор. Потом все необходимые трейсы и метрики попадают в контекст, а он пропагируется по дереву вызова другим методом вниз.

Приложение наследует от корневого span остальные spans, просто используя OpenTelemetry API и данные, которые лежат в контексте. При этом импортируемые библиотеки получают на вход методы контекст, пытаются считать из этого метода информацию о корневом span. Если его нет, создают свой, и дальше инструментируют логику. Таким образом, вы можете сначала инструментировать свою библиотеку.

Более того, вы можете инструментировать все, но не настраивать экспортеры данных, и просто задеплоить это.

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

Таким образом, если у вас какая-то опенсорсная библиотека, вы можете инструментировать ее при помощи OpenTelemetry. Потом люди, которые ее используют, настроят у себя OpenTelemetry и будут использовать эти данные.

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

У нас в компании активно применяется стандарт OpenCensus для трейсинга и мониторинга микросервисного ландшафта компании. Планируется внедрение OpenTelemetry после его релиза.
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru