Стиль архитектуры микрослужб

Azure

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

Логическая схема стиля архитектуры микрослужб.

Что такое микрослужбы?

  • Микрослужбы — это небольшие, независимые и слабо связанные решения. Создавать и обслуживать их может даже небольшая команда разработчиков.

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

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

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

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

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

Помимо самих служб, некоторые компоненты обладают типичной архитектурой микрослужб:

Управление и оркестрация Этот компонент отвечает за размещение служб на узлах, определение сбоев, перераспределение служб между узлами и другие операции. Как правило, этот компонент является коммерческим продуктом (например, Kubernetes), а не разрабатываемым по заказу.

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

Преимущества использования шлюза API:

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

  • Службы могут использовать протоколы обмена сообщениями, которые не работают в Интернете, например AMQP.

  • Шлюз API может выполнять другие сквозные функции, например аутентификацию, ведение журнала, завершение запросов SSL и балансировку нагрузки.

  • Готовые политики, такие как регулирование, кэширование, преобразование или проверка.

Льготы

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

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

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

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

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

  • Масштабируемость. Службы можно масштабировать независимо. Благодаря этому вы можете горизонтально увеличивать масштаб подсистем, для которых требуются дополнительные ресурсы, не увеличивая масштаб всего приложения горизонтально. С помощью оркестратора, такого как Kubernetes, можно упаковать более высокую плотность служб на один узел, что позволяет более эффективно использовать ресурсы.

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

Сложности

Все преимущества микрослужб имеют и обратную сторону. Ниже описаны некоторые моменты, которые следует учитывать при выборе архитектуры микрослужб.

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

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

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

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

  • Целостность данных. Каждая микрослужба отвечает за сохранение собственных данных. В результате согласованность данных в нескольких службах может быть проблемой. Различные службы сохраняют данные в разные времена, используя разные технологии и потенциально разные уровни успеха. Если несколько микрослужб участвуют в сохранении новой или измененной даты, маловероятно, что полное изменение данных может считаться транзакцией ACID. Вместо этого метод более выравнивается с BASE (в основном доступное, мягкое состояние и в конечном итоге согласовано). Применяйте итоговую согласованность, где это возможно.

  • Управление. Для успешной работы с микрослужбами требуется современная культура DevOps. Коррелированное ведение журнала для разных служб может оказаться сложной задачей. Как правило, ведение журнала необходимо коррелировать с несколькими вызовами службы для одной операции пользователя.

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

  • Навыки. Микрослужбы являются распределенными системами. Тщательно оцените знания и опыт своей команды для работы с этими службами.

Рекомендации

  • Моделируйте службы для определенной сферы деятельности.

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

  • Данные должны храниться в службе, к которой они относятся. Используйте наиболее подходящее хранилище для каждой службы и каждого типа данных.

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

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

  • Перенесите нагрузку сквозных функций, таких как аутентификация и завершение SSL-запросов, в шлюз.

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

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

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

Следующие шаги

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