Современные шаблоны проектирования архитектуры

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

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

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

Вот список шаблонов, которые мы рассмотрим в этой статье:

1. Автоматическое прерывание  (Circuit Breaker).
2. Разделение ответственности команд и запросов (CQRS).
3. Определение источников событий.
4. Шаблон расширения (Sidecar).
5. Backend-for-Frontend.
6. Шаблон подавления (Strangler).

Итак, начнем.

Автоматическое прерывание (Circuit Breaker)

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

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

На диаграмме выше показана реализация схемы автоматического прерывания: когда сервис-1 понимает, что при вызове сервиса-2 происходят непрерывные сбои или тайм-ауты, вместо повторной попытки сервис-1 отключает вызовы сервиса-2 и возвращает резервный ответ.

Существуют популярные библиотеки с открытым исходным кодом, например Hystrix от Netflix или Reselience4J, которые можно применить для удобной реализации этого шаблона.

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

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

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

Когда использовать этот шаблон

  • Когда сервис зависит от другого удаленного сервиса, и есть вероятность его отказа в некоторых сценариях.
  • Когда сервис имеет очень высокую зависимость (например, сервисы мастер-данных).

Когда не следует использовать этот шаблон

  • Когда вы имеете дело с локально-зависимыми объектами, автоматическое прерывание может привести к чрезмерному потреблению ресурсов.

Разделение ответственности команд и запросов (CQRS)

CQRS (Command Query Responsibility Segregation)  —  очень полезный шаблон для современных приложений, взаимодействующих с хранилищами данных. Он основан на принципе разделения операций чтения (запрос) и записи/обновления (команда) в хранилище данных.

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

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

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

Примечание. В настоящее время большинство баз данных PaaS предоставляют возможность создавать реплики для чтения (Google Cloud SQL, Azure SQL DB, Amazon RDS и т.д.) для хранилищ данных, которые значительно упрощают репликацию данных.

Многие корпоративные базы данных также предоставляют эту возможность, если вы имеете дело с локальными БД.

Примечание. Сейчас также есть тенденция реализовывать реплики чтения как быстрые и производительные базы данных NoSQL, к примеру MongoDB и Elasticsearch.

Когда использовать этот шаблон

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

Когда не следует использовать этот шаблон

  • Когда вы создаете обычное приложение CRUD, в котором не ожидается огромного количества одновременных операций чтения и записи.

Определение источников событий

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

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

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

Примечание. Большинство поставщиков облачных услуг поддерживают службы обмена сообщениями, например Google Pub/Sub, Azure Service Bus, AWS SQS и т.д. Эти службы в сочетании с надежными хранилищами данных могут применяться для реализации этого шаблона.

Когда использовать этот шаблон

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

Когда не следует использовать этот шаблон

  • Когда регулярных CRUD-операций достаточно, чтобы удовлетворить потребности пользователя.

Шаблон расширения (Sidecar)

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

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

Такой тип внешних устройств помогает абстрагировать коммуникации типа L4/L7. Sidecar-расширения, подобные Envoy Proxy, даже способствуют более высокой безопасности при взаимной реализации протокола TLS.

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

Когда использовать этот шаблон

  • Когда вы имеете дело с множеством однообразных микросервисов в области продукта.
  • Когда вы имеете дело с устаревшими приложениями, которые не справляются с новыми проблемами коммуникации и безопасности.

Когда не следует использовать этот шаблон

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

Backend-for-Frontend (BFF)

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

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

В таких случаях может оказаться полезным шаблон Backend-for-Frontend. Здесь ожидается, что вы создаете/настраиваете сервисы бэкенда под конкретный внешний интерфейс.

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

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

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

Когда использовать этот шаблон

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

Когда не следует использовать этот шаблон

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

Подавление (Strangler)

Если вы работаете в организации, которая находится в процессе модернизации приложений, то шаблон подавления, он же Strangler, именно то, что вам нужно. Шаблон проектирования Strangler предполагает создание внешнего интерфейса поверх легаси-кода и нового кода приложения, таким образом предоставляя потребителю обобщенный вид.

Эта модель отделяет пользователей от деятельности, связанной с миграцией приложения.

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

Вам только нужно решить, хотите ли вы сохранить интерфейс после миграции или избавиться от него.

Когда использовать этот шаблон

  • Когда вы переносите или модернизируете сложное, сильно зависимое приложение, например в случаях миграции ERP-систем.

Когда не следует использовать этот шаблон

  • Когда переход достаточно прост, а прямая замена  —  наилучший вариант.

Читайте также:

Читайте нас в Telegram, VK и Яндекс.Дзен


Перевод статьи Tanmay Deshpande: Modern-Day Architecture Design Patterns for Software Professionals

Предыдущая статьяОсновы работы с Git
Следующая статьяПереоткрываем для себя эмулятор Android для ускорения тестирования