[Перевод] Наиболее используемые шаблоны проектирования распределенных систем
Шаблоны проектирования распределенных систем предоставляют разработчикам проверенные решения и передовые методы проектирования и внедрения распределенных приложений.
Они воплощают в себе десятилетия коллективного опыта и играют важную роль в решении проблемы сложности распределенных вычислений.
Эти шаблоны также отличаются от шаблонов микросервисов, но имеют совпадения, такие как автоматический выключатель, а некоторые из наиболее широко используемых шаблонов распределенных систем включают в себя:
Данная статья переведена с английского с адаптациями в рамках курса «Разработка распределенных систем и веб-сервисов»
Амбассадор
Шаблон «Амбассадор» фокусируется на разгрузке всех основных задач, которые критически важны для приложений, помимо бизнес-логики, чтобы приложения могли сосредоточиться только на критически важных вариантах использования.
Он выступает в качестве «посредника» между приложениями и службами, с которыми он взаимодействует, разгружая такие задачи, как ведение журнала, мониторинг или обработка повторных попыток, а также ограничение скорости.
Например, K8 использует Envoy в качестве посредника для простого взаимодействия между службами.
Envoy Gateway и сервисная сетка
Istio предоставляет множество функций, которые делают разработку и поставку программного обеспечения более быстрой, простой и безопасной.
Безопасность: Istio помогает командам разработчиков приложений достичь безопасности по принципу нулевого доверия с помощью возможности определять и внедрять политики аутентификации, авторизации и контроля доступа.
Обнаружение служб: одной из основных потребностей приложения, работающего в производственной среде, является высокая доступность. Это требует масштабирования количества экземпляров служб с ростом нагрузки и уменьшения масштаба при необходимости экономии затрат. Возможность обнаружения служб Istio отслеживает все доступные узлы, готовые принять новые задачи. В случае недоступности узла обнаружение служб удаляет узел из списка доступных узлов и прекращает отправку новых запросов на узел.
Управление трафиком: используя прокси-серверы Envoy, Istio обеспечивает гибкость для точного управления трафиком среди доступных сервисов. Istio предоставляет такие функции, как балансировка нагрузки, проверки работоспособности и стратегии развертывания. Istio позволяет балансировать нагрузку на основе алгоритмов, которые включают циклический перебор, случайный выбор, взвешенные алгоритмы и т. д. Istio выполняет постоянные проверки работоспособности экземпляров сервисов, чтобы убедиться, что они доступны, перед маршрутизацией запроса трафика. На основе типа развертывания, используемого в конфигурации, Istio направляет трафик на новые узлы по взвешенному шаблону.
Устойчивость: Istio устраняет необходимость кодирования автоматических выключателей в приложении. Istio помогает архитекторам платформы определять такие механизмы, как тайм-ауты для службы, количество повторных попыток и запланированный автоматический отказ систем высокой доступности (HA), без ведома приложения.
Наблюдаемость: Istio отслеживает сетевые запросы и отслеживает каждый вызов по нескольким сервисам. Istio предоставляет телеметрию (такую как задержка, насыщение, состояние трафика и ошибки), которая помогает SRE понимать поведение сервиса и устранять неполадки, обслуживать и оптимизировать свои приложения.
Ссылка: https://blog.devops.dev/operational-efficiency-monitoring-and-analytics-setting-up-managed-metrics-using-prometheus-and-54d3cb86280e
Автоматический выключатель
Представьте, что в доме прорвало водопроводную трубу. Первое, что мы должны сделать, это закрыть главный клапан, чтобы предотвратить дальнейший ущерб. Схема автоматического выключателя работает аналогичным образом, предотвращая каскадные отказы в распределенных системах.
Обслуживание каскадных отказов без автоматического выключателя
Когда обслуживание становится недоступным, автоматический выключатель останавливает запросы, позволяя ему восстановиться; мы используем схемы автоматического выключателя, чтобы предотвратить дальнейшие повреждения.
Схема автоматического выключателя
Закрыто:
В этом состоянии автоматический выключатель позволяет осуществлять нормальную связь со службой, и запросы проходят через службу.
Автоматический выключатель отслеживает ответы от службы на наличие ошибок (код HTTP 4XX, 5XX) . Если ответы успешны (200 OK) без проблем, он остается в закрытом состоянии.
Открыто:
когда количество сбоев достигает порогового значения, автоматический выключатель переключается в открытое состояние (код HTTP 4XX, 5XX с некоторым пороговым значением < 30), предотвращая попадание запросов на службу и предоставляя резервный ответ.
(Пороговое значение, например, 30 сбоев в течение 10 секунд)
Полуоткрытый:
После истечения времени ожидания или интервала сброса автоматический выключатель переходит в состояние «Полуоткрытый».
Это позволяет ограниченному количеству тестовых запросов пройти к сервису, чтобы увидеть, восстановился ли сервис или нет.
Если тестовые запросы успешны (200 OK), это означает, что сервис восстановился, и автоматический выключатель возвращается в состояние «Закрытый».
Если какой-либо из тестовых запросов не удается, это означает, что сервис все еще имеет проблемы, и автоматический выключатель переходит в состояние «Открытый», чтобы блокировать дальнейшие запросы.
Существует несколько инструментов и фреймворков, реализующих шаблон автоматического выключателя. Вот несколько популярных вариантов:
Netflix Hystrix:
Hystrix — это библиотека Java с открытым исходным кодом, которая обеспечивает реализацию шаблона автоматического выключателя для управления отказоустойчивостью и задержками в распределенных системах и архитектурах микросервисов.
Примечание: Netflix официально перешел в режим технического обслуживания, и пользователи переходят на использование альтернативных решений, таких как resilience4j или Sentinel.
Ключевые особенности Resilience4j включают в себя:
Повтор: позволяет определять стратегии повтора для неудачных операций и указывать, сколько раз операция должна быть повторена.
Ограничитель скорости: позволяет контролировать трафик в некоторые части вашего приложения, ограничивая скорость запросов к службе, чтобы предотвратить их перегрузку.
Откат: позволяет определять функции отката или ответы при неудачной операции и корректно завершать работу, улучшая пользовательский опыт.
2. Resilience4j:
Resilience4j — это легкая и простая в использовании библиотека, которая предлагает мощную реализацию автоматического выключателя, вдохновленную Netflix Hystrix, но разработанную с использованием подхода функционального программирования.
3.Istio:
Istio — это платформа сервисной сетки, которая помогает вам управлять трафиком между микросервисами. Она предоставляет ряд функций, включая:
Автоматический выключатель: модель отказоустойчивости, которая может направлять трафик от неработоспособных микросервисов и автоматически повторять неудачные запросы.
4.Sentinel:
Это библиотека с открытым исходным кодом, которая обеспечивает мониторинг служб и контролирует трафик.
Она может использоваться для реализации разрыва цепи, ограничения скорости.
Sentinel может работать как на Java, так и на других языках.
5.Amazon App Mesh:
Amazon App Mesh — это управляемая сервисная сетка, которая позволяет вам отслеживать и контролировать сервисы, работающие на AWS.
Она предоставляет такие функции, как разрыв цепи, повторные попытки и многое другое для повышения надежности ваших микросервисов.
CQRS (разделение ответственности команд и запросов)
CQRS разделяет операции чтения и записи по разным базам данных, команды выполняют обновление данных, запросы выполняют чтение данных.
Платформа электронной коммерции может иметь большое количество запросов на чтение для листинга товаров, но меньше запросов на запись для размещения заказов.
Шаблон проектирования CQRS
В монолитных приложениях одна база данных обычно обрабатывает как запросы, так и операции обновления, управляя сложными объединениями и задачами CRUD . По мере усложнения приложений эти операции могут стать неуправляемыми.
Например , запрос, требующий объединения более 10 таблиц, может заблокировать базу данных из-за задержки, в то время как операции CRUD со сложными проверками также могут вызывать блокировки.
Чтобы решить эту проблему, CQRS разделяет операции чтения и записи по разным базам данных, применяя принцип «разделения интересов» . Это позволяет использовать, например, базу данных NoSQL для операций чтения и реляционную базу данных для записи.
Понимание поведения приложения имеет решающее значение. Если приложение интенсивно читает (понимание нефункционального требования соотношения чтения и записи), архитектура должна отдавать приоритет оптимизации операций чтения.
В примере приложения электронной коммерции:
Команды должны быть действиями с операциями на основе задач, такими как «добавить товар в корзину» или «оформить заказ». Поэтому команды могут обрабатываться системами брокеров сообщений, которые обеспечивают обработку команд асинхронным способом.
Запросы никогда не изменяют базу данных. Запросы всегда возвращают данные JSON с объектами DTO. Таким образом, мы можем изолировать команды и запросы.
Чтобы изолировать команды и запросы, лучше всего физически разделить базу данных чтения и записи с помощью 2 баз данных . Таким образом, если наше приложение интенсивно читает, что означает больше чтения, чем записи, мы можем определить пользовательскую схему данных, оптимизированную для запросов.
Шаблон материализованного представления — хороший пример для реализации чтения баз данных. Потому что таким образом мы можем избежать сложных соединений и отображений с предопределенными мелкозернистыми данными для операций запроса.
Благодаря этой изоляции мы можем даже использовать разные базы данных для чтения и записи типов баз данных, например, использовать базу данных документов no-SQL для чтения и использовать реляционную базу данных для операций CRUDI.
Теперь можно проектировать наши базы данных микросервисов заказов.
Разделить 2 базы данных для микросервисов упорядочения:
1 для базы данных записи для реляционных задач, 2
для базы данных чтения для запросов
Поэтому, когда пользователь создает или обновляет заказ, я собираюсь использовать реляционную базу данных для записи, а когда пользователь запрашивает заказ или историю заказов, я собираюсь использовать базу данных для чтения без SQL. И сделать их согласованными при синхронизации двух баз данных с использованием системы брокера сообщений с применением шаблона публикации/подписки.
Далее мы можем рассмотреть технологический стек этих баз данных.
SQL Server( PostgreSQL/MySQL) для реляционной базы данных записи и использование Cassandraдля базы данных чтения без SQL. Конечно, мы будем использовать Kafka для синхронизации этих 2 баз данных с обменами темами pub/sub Kafka .
Поиск мероприятий
Думайте об источнике событий как о ведении журнала текущих событий. Вместо хранения текущего состояния данных этот шаблон записывает последовательность событий, которые привели к текущему состоянию.
Поиск мероприятий
Преимущества: обеспечивает полный контрольный журнал, позволяет обрабатывать сложные события и повышает согласованность. С помощью источника событий мы также можем реализовать отладку с перемещением во времени или воспроизведение событий для аналитических целей.
Проблемы: требуется тщательное проектирование схем событий и обработка воспроизведения событий для восстановления состояния.
Модель коляски
Развертывает вспомогательные компоненты (sidecars) наряду с основными контейнерами служб для управления сквозными задачами, такими как ведение журнала, мониторинг и настройка.
Концепция Sidecar в Kubernetes становится популярной. Контейнеры должны фокусироваться на одной задаче и делать ее хорошо, а шаблон Sidecar поддерживает это, отделяя основную бизнес-логику от дополнительных задач.
Этот шаблон включает два контейнера на одном узле. Первый — это контейнер основного приложения с базовой логикой, а второй — контейнер Sidecar, который улучшает основное приложение, работая параллельно в одном Pod. Они совместно используют такие ресурсы, как файловая система, диск и сеть.
Шаблон Sidecar также позволяет развертывать различные компоненты одного и того же приложения в изолированных контейнерах, что выгодно для совместного использования общих компонентов в архитектуре микросервисов, таких как свойства регистрации, мониторинга и конфигурации.
Istio Sidecar
Преимущества: Улучшает модульность и удобство обслуживания.
Примеры: Istio для сервисной сетки, Envoy в качестве вспомогательного прокси-сервера.
Выбор лидера
В распределенных системах некоторые задачи требуют одного лидера. Алгоритмы выбора лидера гарантируют, что один узел будет назначен лидером.
В этом шаблоне гарантируется, что за определенную задачу или ресурс отвечает только один узел.
Если узел-лидер выходит из строя, оставшиеся узлы выбирают нового лидера. Zookeeper и т. д. используют эти шаблоны для управления распределенными конфигурациями.
Наличие назначенного лидера позволяет избежать конфликтов и обеспечить единообразное принятие решений в рамках распределенной системы.
На диаграмме выше:
Три сервера приложений Spring Boot, работающих на портах 8081, 8082 и 8083, используются в качестве базы данных, в которой хранятся данные Persona.
Каждый сервер Spring Boot подключается к автономному серверу Zookeeper во время запуска.
Каждый сервер приложений Spring Boot будет поддерживать и хранить информацию о кластере в своей памяти. Эта информация о кластере будет сообщать текущие активные серверы, текущего лидера кластера и все узлы, которые являются частью этого кластера.
Мы создадим 2 API GET для получения информации о кластере и данных о людях и 1 API PUT для сохранения данных о людях.
Любой запрос на обновление Person, поступающий на сервер приложения, будет отправлен Leader, который, в свою очередь, передаст запрос на обновление всем активным серверам/подписчикам.
Любой сервер, который снова запустится после того, как он был мертв, будет синхронизировать данные Person от лидера.
Преимущества: Обеспечивает скоординированность действий и последовательность.
Примеры: смотритель зоопарка и т.д.
Издатель/Подписчик
Этот шаблон позволяет службам общаться асинхронно. Издатели отправляют сообщения без ведома подписчиков, а подписчики получают сообщения, представляющие интерес.
Например, модель «издатель/подписчик» похожа на службу доставки газет: издатели публикуют события, не зная, сколько подписчиков их получают, а подписчики слушают события, которые им интересны.
Этот шаблон обеспечивает лучшую масштабируемость и модульность, например, Google Cloud Pub/Sub обеспечивает асинхронный обмен сообщениями между службами, что упрощает поддержку и масштабирование сложных приложений.
Очередь событий Kafka
Ключевым моментом является тот факт, что Pub/Sub позволяет передавать сообщения между различными компонентами системы, при этом компоненты не знают об идентичности друг друга (они разъединены).
Pub/Sub предоставляет фреймворк для обмена сообщениями между издателями (компонентами, которые создают и отправляют сообщения) и подписчиками (компонентами, которые получают и потребляют сообщения)
Преимущества: Разделяет производителей и потребителей сообщений, улучшает масштабируемость и гибкость.
Примеры: Kafka, RabbitMQ, AWS SNS, Google Cloud Pub/Sub.
Шардинг
Разделяет набор данных на более мелкие, более управляемые части (осколки), которые можно распределить по нескольким базам данных или узлам.
Разделение похоже на разделение большой пиццы на более мелкие кусочки, что упрощает обращение с ней.
Шардинг — это метод распределения данных по нескольким узлам в системе. Он повышает производительность и масштабируемость.
Каждый осколок содержит подмножество данных, что снижает нагрузку на любой отдельный узел.
Шардинг
Такие базы данных, как MongoDB и Cassandra, используют сегментирование для эффективной обработки больших объемов данных.
Шардинг также может помочь добиться лучшей локальности данных, сократить задержки в сети и ускорить выполнение запросов.
Для справки, между шардингом и разделением есть существенные различия. Мы подробно объясним эти термины далее.
Разделение
Разделение — это общий термин для разделения базы данных по определенной оси для создания нескольких меньших баз данных. Вы можете разделить базу данных:
вертикально: т.е. разделение данных таким образом, чтобы в меньших базах данных были дублирующиеся строки, но разные столбцы
горизонтально: т. е. разделение данных таким образом, чтобы меньшие базы данных имели одинаковые столбцы или одинаковую схему, но разные строки
Шардинг
Шардинг — это подмножество секционирования. Прежде чем мы объясним шардинг и то, что делает его уникальным, давайте сначала рассмотрим, как работает масштабирование данных. По мере увеличения объема данных вам может также потребоваться увеличить емкость хранилища вашей базы данных. Вы можете выполнить вертикальное масштабирование (добавить дополнительный ЦП, ОЗУ, хранилище и т. д.) или горизонтальное масштабирование (добавить больше узлов или машин на ваш сервер). Мы также могли бы описать эти варианты как масштабирование вверх или масштабирование в сторону уменьшения
Типы шардинга:
Алгоритмическое шардинг: При алгоритмическом шардинге клиент может определить базу данных заданного раздела без посторонней помощи. При динамическом шардинге отдельная служба локатора отслеживает разделы среди узлов.
Динамическое шардинг: При динамическом шардинге внешний локатор определяет местоположение записей. Это может быть реализовано несколькими способами. Если мощность ключей разделов относительно низкая, локатор может быть назначен для каждого отдельного ключа. В противном случае один локатор может адресовать диапазон ключей разделов.
Группы сущностей: храните связанные сущности в одном разделе, чтобы обеспечить дополнительные возможности в рамках одного раздела.
Варианты использования
Сайт электронной коммерции, отображающий информацию о заказе/клиенте/товаре, может разбивать или сегментировать данные по странам или регионам, поскольку большинство запросов будут извлекать информацию на основе определенных местоположений.
Аналитическая фирма фондового рынка может разбить данные по компаниям или по (компании, дню), если она хочет провести еще более подробный технический анализ.
Извлекая цену акций с апреля 2010 по декабрь 2010, мы можем запросить Shard 1 и получить данные. Кроме того, каждый шард будет хранить данные в отсортированном порядке для улучшения производительности запроса. Это показано на диаграмме ниже.
Преимущества: Улучшает масштабируемость и производительность.
Проблемы: Усложняет маршрутизацию запросов и управление сегментами.
Переборка
Изолирует компоненты в системе, чтобы отказ одного компонента не приводил к отказу всей системы.
Шаблон Bulkhead особенно полезен в следующих сценариях:
Изоляция ресурсов: когда вам необходимо изолировать ресурсы, используемые внутренними службами потребителей, чтобы предотвратить конфликты за ресурсы.
Изоляция критически важных потребителей: защита критически важных потребителей (услуг) от стандартных потребителей, обеспечение доступности и оперативности критически важных услуг даже во время пиковых нагрузок или сбоев.
Защита от каскадных сбоев: для защиты вашего приложения от каскадных сбоев, которые могут возникнуть, когда проблемы в одной службе влияют на другие.
Похожие шаблоны:
Шаблон Bulkhead можно эффективно комбинировать с другими шаблонами проектирования облаков, включая:
Шаблон автоматического выключения: обеспечивает отказоустойчивость путем предотвращения постоянных вызовов службы, в которой возникают проблемы.
Шаблон повтора: для реализации стратегий повтора в переборках с целью изящной обработки временных сбоев.
Шаблон регулирования: для контроля и ограничения скорости входящих запросов, предотвращая перегрузку перегородки.
Где мы можем реализовать переборку?
Конфигурация Bulkhead в шлюзе API позволяет указать максимальное количество одновременных запросов, которые может обрабатывать API.
Ограничение Bulkhead для API на уровне API . Указывает максимальный лимит одновременных запросов для API, при превышении которого запросы отклоняются.
Это число не включает обратные вызовы, которые получает API. Таким образом, вы можете отдельно указать максимальное количество одновременных обратных вызовов, которые может обработать API.
Код ошибки 503 «Служба недоступна» отправляется клиентской службе при отклонении запросов.
Вы можете настроить требуемый код ошибки и фразу статуса с помощью расширенных настроек. Вы можете настроить требуемый код статуса и сообщение с помощью расширенных настроек pg.bulkhead.statusCode и pg.bulkhead.statusMessage соответственно.
Ограничение Bulkhead для всех API (глобальная политика) . Указывает максимальный лимит одновременных запросов для всех API.
Подобно конфигурации уровня API, вы можете указать максимальное количество одновременных обратных вызовов и возможность повторной обработки отклоненных запросов.
Если вы настроили предел переборки на глобальном уровне для API и настроили другой предел переборки на уровне API, то приоритет будет иметь предел, настроенный на глобальном уровне.
Чтобы переопределить это, необходимо исключить требуемые API из global-policy с помощью фильтров . Вы можете применить требуемые фильтры API при создании или редактировании глобальной политики переборки . Для получения информации о создании глобальных политик и применении фильтров API
Преимущества: Повышает устойчивость и отказоустойчивость.
Примеры: изоляция различных сервисов в архитектуре микросервисов.
Кэш-Aside
Этот шаблон подразумевает явную загрузку данных в кэш из хранилища данных и запись данных в хранилище данных через кэш.
Шаблон кэширования в стороне, также известный как ленивая загрузка, подразумевает прямое взаимодействие кода приложения с кэшем.
При запросе данных приложение сначала проверяет кэш. Если данные найдены, они возвращаются пользователю. Если нет, приложение извлекает данные из первичного источника данных, сохраняет их в кэше, а затем возвращает пользователю.
Этот шаблон подходит для сценариев, где кэш содержит часто используемые данные, что улучшает время отклика и снижает нагрузку на основной источник данных.
Кэширование со сквозной и отложенной записью
Кэширование со сквозной записью подразумевает одновременную запись данных как в кэш, так и в основной источник данных.
Это гарантирует, что кэш и основной источник данных остаются согласованными, но может привести к задержке из-за операции двойной записи.
С другой стороны, кэширование с отложенной записью сначала записывает данные в кэш, а затем асинхронно обновляет первичный источник данных. Хотя кэширование с отложенной записью сокращает задержку, оно может увеличить риск несогласованности данных в случае сбоев или сбоев системы.
Кэширование сквозного и опережающего чтения
Сквозное кэширование подразумевает чтение данных из кэша. Если данные не найдены, они извлекаются из первичного источника данных, сохраняются в кэше и возвращаются пользователю.
Этот шаблон подходит для рабочих нагрузок с интенсивным чтением, где кэширование часто используемых данных может повысить производительность.
Кэширование с опережающим чтением предвосхищает будущие шаблоны доступа к данным и предварительно загружает данные в кэш до того, как они будут запрошены. Это помогает сократить задержку, гарантируя, что требуемые данные будут легко доступны, когда они нужны.
Преимущества: Снижает нагрузку на базу данных, повышает производительность чтения.
Данная статья переведена с английского с адаптациями в рамках курса «Разработка распределенных систем и веб-сервисов».
Habrahabr.ru прочитано 8556 раз