Архитектура

Архитектура микросервисов: как визуализировать сервисы и связи

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

10 мин чтения

Карта сервисов
На этой странице

Почему микросервисы трудно нарисовать#

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

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

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

Что показывать на схеме микросервисов#

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

Сервисы и их владельцы#

Каждый сервис — отдельный блок с понятным именем по его задаче: «Заказы», «Каталог», «Уведомления», а не «svc-17». В описании — язык и основное хранилище, рядом — команда-владелец. Владелец важнее технологии: когда сервис падает, первым делом ищут, кому писать.

Синхронные вызовы#

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

События и сообщения#

Сервис публикует событие в брокер — Kafka, RabbitMQ, NATS — и не ждёт, кто и когда его обработает. Подписчики узнают о нём сами. Это ослабляет связность, но делает поток менее заметным: в коде публикующего сервиса не видно, кто его слушает. Поэтому события на схеме особенно ценны. Брокер рисуют отдельным блоком, связи — пунктиром, а на связи пишут название события.

Данные#

Обычное правило микросервисов — у каждого сервиса своя база, и другие сервисы в неё не ходят. На схеме сервисов базы удобно не рисовать отдельными блоками, а писать в описании сервиса: «Go · PostgreSQL». Если два сервиса всё же делят одну базу, это стоит показать явно — это слабое место, о котором должна знать вся команда.

Шлюз и внешние системы#

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

Одна схема — один вопрос: какие виды схем нужны#

Виды схем микросервисной архитектуры
СхемаНа какой вопрос отвечаетЧто на ней
Карта сервисовКакие сервисы есть и кто за них отвечает?Сервисы по доменам, шлюз, основные синхронные вызовы
Поток событийЧто происходит после события X?Публикующие сервисы, события, подписчики
Поток данныхГде хранятся и куда уходят данные?Источники, хранилища, преобразования, внешние получатели
РазвёртываниеГде и как всё запущено?Кластеры, окружения, балансировщики, сети

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

Карта сервисов по доменам#

Группы — домены и команды. Сплошные линии — вызовы через шлюз, пунктир — события.

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

Поток событий#

События — жёлтые капсулы. Так видно цепочку реакций, которую не найти, читая код одного сервиса.

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

Как не превратить схему в спагетти#

  • Группируйте по доменам, а не по технологиям. Рамка «Логистика» полезнее рамки «Сервисы на Kotlin».
  • Прячьте инфраструктуру. Балансировщики, сетевые прокси, сбор логов и мониторинг — на схему развёртывания, а не на карту сервисов.
  • Подписывайте протоколы: REST, gRPC, название события. Без подписи непонятно, что сломается при отказе.
  • Разделяйте виды связей стилем линии: сплошная — синхронный вызов, пунктир — событие. Договорённость — в легенде.
  • Рисуйте брокер одним блоком. Вместо десятка стрелок «каждый с каждым» — стрелки в брокер и из него.
  • Не показывайте всё сразу. Второстепенные связи уберите или вынесите на отдельную схему конкретного процесса.

Так хуже

Непонятно, где вызов, а где событие, и что сломается, если упадёт «Оплата».

Так лучше

Один синхронный вызов, остальное — события через брокер. Связей меньше, и они читаются.

Как собрать карту сервисов по шагам#

  1. Составьте список сервисов

    Из репозиториев, каталога сервисов или описания развёртывания. У каждого — имя, команда, язык, основное хранилище.

  2. Разложите по доменам

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

  3. Добавьте входы

    Клиентов, API-шлюз и внешние системы. Внешние — нейтральным цветом на краю схемы.

  4. Проведите синхронные вызовы

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

  5. Нарисуйте события

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

  6. Добавьте легенду и дату

    Что значат цвета, пунктир и группы. Дата обновления — чтобы читатель знал, насколько схеме можно верить.

  7. Проверьте с командами

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

Начать можно с шаблона «Архитектура ПО»: группы, карточки с иконками и подписанные связи уже есть, остаётся переименовать и размножить. Как пользоваться метками, цветами и анимацией связей на доске, — в руководстве «Схема архитектуры сервиса». Попробовать можно сразу и без регистрации — в песочнице на главной.

Как поддерживать схему в актуальном виде#

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

  • Владелец у каждой схемы. Карта сервисов — у архитектора или техлида, схемы событий — у команд, чьи процессы на них нарисованы.
  • Правка в той же задаче. Добавили сервис или событие — поправили схему, как документацию.
  • Текст рядом с кодом. Небольшую схему одного домена удобно хранить в репозитории текстом Mermaid — подробнее в статье синтаксис Mermaid: примеры и шпаргалка. Блок-схему из такого текста NodePanel вставит на доску блоками, связями и группами, а доску можно скопировать обратно текстом.
  • Регулярная сверка. Раз в квартал пройдитесь по карте с командами: что появилось, что умерло.

Карта кода — для обзора одного сервиса. Карта кода в NodePanel разбирает папку или zip-архив одного проекта прямо в браузере и строит доски: страницы, маршруты API, вызовы с фронта, таблицы базы и архитектуру — сервисы из docker-compose и зависимости между папками кода. Для микросервиса это быстрый способ увидеть его маршруты и данные, а для монорепозитория с docker-compose — список сервисов.

Частые ошибки#

  • Одна схема на всё. Сервисы, события, базы и серверы вместе — нечитаемо. Разведите вопросы по разным схемам.
  • Вызовы и события выглядят одинаково. Тогда схема не отвечает на главный вопрос: что упадёт вместе с этим сервисом.
  • Брокер как невидимка. События нарисованы стрелками напрямую между сервисами, как будто это вызовы.
  • Нет владельцев. Видно, что сервис есть, но непонятно, кто за него отвечает.
  • Группировка по технологиям. Рамки «Java» и «Go» ничего не говорят о том, как устроен бизнес.
  • Общая база не отмечена. Два сервиса пишут в одну таблицу, а на схеме они независимы.
  • Инфраструктура вперемешку с логикой. Прокси, сети и мониторинг заслоняют то, ради чего схему открыли.
  • Схема без даты. Через полгода никто не знает, можно ли ей верить.

Чек-лист схемы микросервисов#

  • Понятно, на какой вопрос отвечает схема: карта сервисов, поток событий, данные или развёртывание.
  • Сервисы сгруппированы по доменам, у каждой группы есть команда-владелец.
  • У каждого сервиса — имя по задаче, язык и основное хранилище.
  • Синхронные вызовы и события различаются стилем линии, есть легенда.
  • На каждой связи — протокол или название события.
  • Брокер нарисован отдельным блоком, события идут через него.
  • Шлюз и внешние системы показаны, внешние — нейтральным цветом.
  • Общие базы и другие слабые места отмечены явно.
  • Инфраструктура вынесена на отдельную схему.
  • Есть дата обновления и владелец схемы.

Если нужна общая доска, где команды правят и обсуждают карту сервисов вместе, — посмотрите страницу схема архитектуры ПО онлайн.

Вопросы и ответы#

Нужно ли рисовать базы данных микросервисов отдельными блоками?

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

Как показать на схеме асинхронные события?

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

Сколько схем нужно для микросервисной системы?

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

Может ли карта кода NodePanel построить схему всех микросервисов?

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

Как не запутаться, если сервисов больше пятидесяти?

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

Архитектура

Как нарисовать архитектуру приложения: схема, которую поймут все

Уровни детализации по модели C4, что показать на схеме, пошаговый план, обозначения и пример веб-сервиса. Как держать схему актуальной, ошибки и чек-лист.11 мин чтения
Схемы из текста

Синтаксис Mermaid: примеры диаграмм и шпаргалка

Шпаргалка по Mermaid: блок-схема flowchart — направление, формы, стрелки, подграфы и стили — и короткие примеры sequence, class, state, ER, gantt, pie и mindmap.13 мин чтения
Процессы

Что такое блок-схема и как её правильно составить

Что такое блок-схема, что означают её фигуры по ГОСТ 19.701-90, какие бывают виды схем и как составить схему без ошибок: правила, примеры и чек-лист.10 мин чтения