Мы сделали 2 подсистемы внутри Apache Ignite. В статье расскажу про их архитектуру: Всем привет! Меня зовут Николай Ижиков. Я работаю в Сбербанк Технологии над развитием Open Source продуктов. Замечание 1: «сделано» означает, что эта функциональность доступна в master Apache Ignite, можно собрать и посмотреть как все работает. Функционал попадёт в релиз 2.8 Apache Ignite, который будет выпущен в начале 2020 года.  Замечание 2: Статья про архитектуру, не будет конкретных чисел, которые понадобятся для мониторинга Apache Ignite.   Замечание 3: Функционал будет доступен в релизе 2.8, который случится скоро, а может-быть даже раньше.  Apache Ignite распределенная in-memory платформа. Предоставляет много API: для кеширования, распределённых вычислений, сервисов (построения микросервисной архитектуры), обеспечивает транзакционность.  Допустим, у вас есть система и она как-то работает в проде. К вам обязательно придут администраторы и спросят: "А как посмотреть что происходит внутри, как система себя ведёт? Мы хотим узнать о происходящих процессах, до того момента как они приведут к падению или изменению поведения, которое невозможно скрыть." По сути вопросы сводятся к следующим: Для ответов на часть этих вопросов необходимо разработать подсистему мониторинга. В случае распределенной системы мониторинг это: Подсистема мониторинга нужна, с этим определились. Но, перед тем как разрабатывать мы должны понять, что у нас есть уже. Получилось следующее: Картина идеального мира: Необходимо уточнить как происходит работа в Open Source community над такими большими и объемными задачами. У нас есть процесс, который называется Ignite Enhancement Proposal (IEP), автор формулирует предлагаемые изменения, мотивацию, API, фазы изменения.
Было предложено несколько важных и долгоиграющих решений по дизайну: Ignite распределённая система: есть глобальное состояние, поддерживаемое между нодами. В текущей реализации есть глобальные метрики, которые отражают состояние всего кластера. С моей точки зрения, это неверный подход. Если метрика должна быть глобальной это означает, что Ignite должен обеспечивать консистентность подсчета этой метрики по всему кластеру. Что ведет к тому, что Ignite выполняет не свойственные для себя функции — правильный подсчет метрик и поддержание их в актуальном состоянии. Мое глубокое убеждение — метрики должны быть локальными. После их сбора в системе агрегации метрик (prometheus, zabbix) мы можем вычислить глобальное состояние. В Ignite много подсистем. Также Ignite должен предоставлять информацию о своём окружении: jvm, диск, памяти, версия ОС и др. Каждая из подсистем Ignite предоставляет свой набор метрик. Есть подсистемы, внутри которых так же есть иерархия. Пример: кеши — хочется смотреть метрики по каждому кешу отдельно.  Так появляется несколько уровней иерархии: кеши, data region'ы, сетевые сообщения от конкретной ноды и т.д. Иерархическая структура отображена в названии метрики, слева направо идут уровни иерархии, разделенные точкой.  Пример: io.dataregion.myregion.TotalAllocatedPages — количество страниц выделенных для Data Region с именем "myregion".  В коде реализовано так: Выделено несколько типов метрик: MetricExporterSpi — каждый из экспортеров работает независимо, по своему протоколу. Он выгружает в любую систему свои метрики, что обеспечивает универсальность и гибкость. Из коробки поддерживаются JMX, SQL, Log, OpenCensus. Кажется, что на вопрос "Что происходит?" мы ответили.
Осталось всего лишь реализовать все нужные метрики. При наличии опыта работы с реляционными БД все понимают идею — везде есть системные представления. Мы назвали сущность system view, но можем показывать ее не только с помощью SQL. Поддерживаются любые протоколы (из коробки еще JMX). Особенности: При экспорте нужно знать схему данных: столбцы и их типы. Эта информация есть в java-классе. Задача выгрузки схемы формулируется следующим образом: Я сделал кодогенерацию: Что получилось:
Интерфейс(SystemViewRowAttributeWalker.java), который умеет обходить свойства объекта для формирования схемы и для выгрузки данных. Реализации интерфейса генерируются автоматически. Заведение system view становится очень простым. После заведения представление становится доступно всем экспортерам. Reflection тормозит — как не удивительно, но не для всех это очевидно. Для обсуждения на dev-list я написал JMH benchmark. Для reflection он берет список методов из класса. В случае walker он вызывает конкретные методы. Walker работает в 4 раза быстрее. Кажется, что на вопрос "Что внутри?" мы ответили.  Сейчас на dev-листе идет очень интересная дискуссия на тему "А правильно ли мы сделали?", а также по процессу замены устаревшего API Презентация — https://www.highload.ru/moscow/2019/abstracts/6111
Видео: