Выдержка из книги "Building microservices"

· 5 min read

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

Microservices

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

  • выбрать наиболее подходящую технологию
  • независимо разрабатывать/деплоить
  • отваливась только часть функциональность
  • независимо маштабировать

В чем разница с SOA?

  • SOA была хорошей идеей, но она не прижилась. (Примечание: спорное утверждение)

Другие способы распила:

  • Шаренные либы - путь в никуда, не можем менять технологию
  • Модули - отличие от либ, что можно делать hot-reloads, e.g.: Erlang modules. Но такой же путь вникуда.

The Evolutionary Architect

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

  • Предоставить принципы, с помощью которых идёт выбор технических решений
  • Сделать набор практик на основе этих принципов
  • Создать команду “управления”, которая следит что выбранные практики и принципы применяются в системах.

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

How to model service

В качестве примера предложили MusicCorp - онлайн-магазин по продаже музыкальных альбомов. Сервисы должны быть слабо связаными (loose coupling) между собой, высоко сцепленными (high cohesion) внутри себя. Магазин разбили на две части: склад и финансы. Склад поделили на три микросервиса: заказы, логистика, инвентарь. Дальше ситуации:

  • Финансы лезут в базу инвентаря - всё плохо, протекло
  • Финансы получают сообщения из склада - всё плохо, одна и та же модель значит разное для сервисов.
  • Финансы идут в API микросервиса инвентаря - всё плохо, склад потерял свои границы.

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

Integration

Как можно между собой микросервисы интегрировать:

  • Шаренная база данных - никогда так не делайте, изменения одного микросервиса сломают остальные.
  • RPC - сервис посылает запрос на выполнение команды. Провоцирует каскадные падения :(
  • Event-based - сервис создаёт события в шины, остальные сервисы подписываются и делают нужное. Низкая связность, но сложно тестировать.

Как жить фронту при этом?

  • Один фронт используют несколько API при построение страницы
  • Фронты пилят виджеты, которые могут встраиваться и каждый использует своё API
  • Ставим API gateway для всех
  • Ставим API gateway под каждого консьюмера - BFF

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

Splitting the Monolith

Находим куски кода, которые могут работать максимально независимо (seams, см. Working with legacy code). Для начала мы можем разнести их в разную схему базы данных, но живут они в монолите. Каждый модуль может ходить в свою схему. MusicCorp разбили на customers, finance, inventory. Плюс остался reporting, который может ходить везде.

Дальше начинаются пляски с reporting, варианты:

  • Репортинг использует реплику базы - плохой путь, потому что шаренные модели
  • Кастомеры делают дамп в своём формате для репортинга - вполне норм, но могут быть не реалтайм данные.
  • Кастомеры делают API, которая делает дамп ondemand - лучший вариант, при этом много говорилось как его праивльно запроектировать.
  • Последний вариант, кастомеры пишут все изменения в шину и есть сервис который аггрерует это для репортинга.

Deployment

CI/CD, билды, образы, контейнеры. Скорее всего и так всё знаете.

Testing

Пирамида тестирования - юнитов как можно больше, UI как можно меньше. Владельцы микросервисов должны писать юнит и сервис тесты с моками/стаббами сервисов, которые он использует. End-to-end тесты должны писаться отдельно, запускаться отдельно и тестировать все микросервисы вживую. Если тесты часто падают либо чиним, либо выкидываем.

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

Monitoring

  • Сначала собирайте низкоуровневые метрики: request rate, response timing, потом переходите на уровень приложения
  • Трекайте что нижележащие сервисы живы, используйте circuit breakers.
  • Стандартизируйте как вы собираете метрики.
  • Все должны логировать в стандартное место. Так как их потом надо аггрегировать, то ещё и в стандартном формате
  • Мониторьте всё что ниже приложения: OS, CPU, MEM.
  • Делайте дашборды и call-to-action алерты.
  • Прокидывайте ID между сервисами.

Security

Api ключи Клиентские сертификаты Разделение по сеткам Для пользователей SSO

Conway’s law

Trivia: Windows Vista получилось такой какой есть, потому что там были feature based команды. Не делайти команды по фичам, делайте по доменам. Ничего не будет работать, если команды будут друг на друга завязаны, или кто-то с кем-то не будет договариваться. За один сервис - отвечает одна команда.

Microservices at Scale

Нужно быть готовым к тому, что всё может упасть, поэтому CAP теорема нам в помощь и выбирайте два из трёх:

  • Response time/latency
  • Availibility
  • Durability of data

Предусматривайте graceful degradation. Лучше отвалиться, чем тормозить и старайтесь знать ограничения сервисов. Timeout’ы, пуллинг, идемподентность - наше всё.

Не забудьте делать документацию по API!

Итого

  • Моделируйте микросервисы вокруг бизнес-концепта
  • Пропогандируйте культуру автоматизации
  • Скрывайте сложность внутри: схему базы, язык, фреймворк, всё что можете, - для этого и нужно API
  • Децентрилизируйте: предпочитайте тупые миддлвари и умные ручки
  • Независимые релизы
  • Назависимые падения
  • Прозрачность: метрики, логи, вот это вот всё.