Привет, Хабр! Меня зовут Сергей Лежнин, я старший архитектор Сбертеха.
Одно из направлений моей работы — Единая фронтальная система.
В данной системе имеется сервис управления параметрами конфигурации.
Он используется многими пользователями, сервисами и приложениями, что требует высокой производительности.
В этом посте я расскажу, как этот сервис развивался от первой, самой простой, до текущей версии и почему мы в итоге развернули всю архитектуру на 180 градусов.
С этого мы и начали — это первая реализация сервиса управления параметрами:
Клиент запрашивает параметры конфигурации у сервиса.
Сервис транслирует запрос в базу данных, получает ответ и возвращает его клиенту.
Параллельно с помощью своего отдельного сервиса администраторы могут управлять параметрами: добавлять новые значения, изменять текущие.
У этого подхода есть одно преимущество – простота.
Минусов больше, хотя все они связаны:
- частый доступ к хранилищу по сети,
- высокая конкуренция за доступ к базе данных (у нас она расположена на одном узле),
- недостаточная производительность.
В результате данная схема не прошла нагрузочное тестирование.
Второй этап: мы решили кэшировать данные на стороне сервиса.
Здесь по запросу данные изначально загружаются в общий кеш и возвращаются из кеша при последующих запросах.
Администратор сервиса не только управляет данными, но и помечает их в кеше, чтобы при изменении они обновлялись.
Таким образом мы сократили количество обращений к хранилищу.
При этом синхронизация данных была простой, поскольку служба администратора имеет доступ к кэшу в памяти и управляет сбросом параметров.
С другой стороны, если произойдет сбой в сети, клиент не сможет получать данные.
Да и вообще логика получения данных усложняется: если данных нет в кеше, нужно достать их из базы, поместить в кеш и только потом вернуть.
Его необходимо развивать дальше.
Третий этап разработки — кэширование данных на стороне клиента:
Клиент имеет оболочку для доступа к сервису («клиентский модуль»), за которой скрывается локальный кэш данных.
Если при запросе нужных данных нет в кеше, происходит обращение к сервису.
Сервис запрашивает параметры из базы данных и возвращает их.
По сравнению с предыдущей схемой здесь сложнее управление кэшированием.
Для сброса параметров сервис должен уведомить клиентов об изменении этих параметров.
В этой архитектуре мы уменьшаем количество обращений к сервису и к базе данных.
Теперь, если параметр уже был запрошен, он вернется клиенту без обращений к сети, даже если сервис или база данных недоступны.
С другой стороны, большим недостатком является то, что логика обмена данными с клиентом усложняется; вам придется его дополнительно уведомить через какой-нибудь сервис - например, очередь сообщений.
Клиент должен подписаться на тему, ему приходят уведомления об изменении параметров, а клиент должен сбросить их в своем кеше, чтобы получить новые значения.
Довольно сложная схема.
Наконец, мы подошли к последнему на данный момент этапу.
В этом нам помогли основные принципы, сформулированные в Реактивном Манифесте.
- Отзывчивость: система реагирует максимально быстро.
- Устойчивость: система продолжает реагировать даже в случае сбоя.
- Эластичность: система использует ресурсы в соответствии с нагрузкой.
- Message Driven: обеспечивается асинхронность и свободный обмен сообщениями между компонентами системы.
Общий принцип таков: клиент подписывается на параметр конфигурации, и при изменении его значений сервер уведомляет об этом клиента.
Приведенная выше диаграмма немного упрощена: она не отражает того, что при регистрации клиента ему необходимо инициализироваться и получить начальное значение.
Но есть в этом главное: стрелки изменили направление.
Раньше клиент или кеш активно запрашивали у сервиса изменение данных, но теперь сервис сам передает события об изменении данных, и они обновляются у клиента.
Эта архитектура имеет несколько важных преимуществ.
Количество вызовов службы и хранилища сокращается, поскольку клиент не запрашивает их активно.
Фактически, каждый обязательный параметр доступен только один раз, когда вы на него подписываетесь.
Тогда клиент просто получает поток изменений.
Доступность данных увеличивается, поскольку у клиента всегда есть значение — оно кэшируется.
И вообще, эта схема обмена параметрами довольно проста.
Единственным недостатком этой архитектуры является неопределенность при инициализации данных.
До тех пор, пока не произойдет первое обновление подписки, значение параметра остается неопределенным.
Но это можно решить, установив для клиента значения параметров по умолчанию, которые при первом обновлении заменяются текущими.
Выбор технологии
Утвердив схему, мы начали поиск продуктов для ее реализации.Выбирайте между Vertx.io , Акка.
ио И Весенние ботинки .
В таблице сведены интересующие нас характеристики.
У Vertx и Akka есть актеры, а у Sping Boot есть библиотека микросервисов, которая по сути аналогична актерам.
То же самое и с реактивностью: у Spring Boot есть собственная библиотека WebFlux, реализующая те же возможности.
Мы оценили легкость примерно в пределах таблицы.
Что касается языков, то из трёх вариантов Vertx считается полиглотом: он поддерживает Java, Scala, Kotlin и JavaScript. У Akka есть Scala и Java; Kotlin, вероятно, тоже можно использовать, но прямой поддержки нет. В Spring есть Java, Kotlin и Groovy. В итоге победил Vertx. Кстати, об этом много говорили на конференции JUG, да и вообще многие компании этим пользуются.
Вот скриншот с сайта разработчика:
На Vertx.io схема реализации нашего решения выглядит следующим образом:
Мы решили хранить параметры не в базе данных, а в Git-репозитории.
Мы можем легко использовать этот относительно медленный источник данных из-за того, что клиент не запрашивает параметры активно и количество запросов уменьшается.
Читалка (вертикаль) считывает данные из репозитория Git в память приложения, чтобы ускорить доступ пользователей к данным.
Это важно, например, при подписке на параметры.
Кроме того, ридер обрабатывает обновления — перечитывает и помечает данные, заменяет старые данные новыми.
Шина событий — это сервис Vertx, который отправляет события между вершинами, а также наружу через мосты.
В том числе и через вебсокет-мост, который в данном случае используется.
Когда поступают события изменения параметров, шина событий отправляет их клиенту.
Наконец, на стороне клиента здесь реализован простой веб-клиент, который подписывается на события (изменения параметров) и отображает эти изменения на страницах.
Как все это работает
Мы покажем вам, как все работает через веб-приложение.Запустите страницу приложения в браузере.
Подписаться на изменение данных с помощью ключа.
Затем заходим на страницу проекта в локальном GitLab, меняем данные в формате JSON и сохраняем в репозиторий.
Приложение отображает соответствующее изменение, что нам и нужно.
Вот и все.
Исходный код демо-версии вы можете найти в моем Git-репозитории и задавайте вопросы в комментариях.
Теги: #git #Хранение данных #Высокая производительность #Анализ и проектирование систем #efs #управление параметрами
-
Так Ли Хорош Pocketbook?
19 Oct, 24 -
Странное Смс Якобы От Билайна.
19 Oct, 24 -
Немного О Медиаконтенте: Стоимость Услуг
19 Oct, 24