Перечислите и кратко опишите паттерны управления

Обновлено: 03.07.2024

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

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

Сценарий транзакций

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

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

Применение шаблона "Сценарий транзакций" способствует сохранению целостности, прозрачности, предсказуемости создаваемого программного обеспечения."Сценарий транзакции"целесообразно рассматривать как механизм организации бизнес-логики ("Модель предметной области").

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

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

Диспетчер

Этот шаблон организации систем предусматривает создание системного компонента, который назначается диспетчером, то есть отвечает за управление и координацию выполнения процессов, исполняемых в программном продукте. При этом нет ограничений на способы выполнения процессов ("последовательно", "параллельно" и пр.).

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

Одним из главных недостатков применения шаблона "Диспетчер" является рекомендация по использованию в так называемых "мягких" системах реального времени (нет строгих временных ограничений).

Применение "Диспетчера" целесообразно в тех случаях, когда группа разработки полностью понимает и имеет различные способы воздействия на все программные компоненты (система представляет собой "прозрачный" ящик).

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

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

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

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

Управление прерываниями

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

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

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

Рекомендации. Применима только в последовательных системах, то есть в таких системах, в которых процессы должны происходить последовательно.

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

Недостатки. Сложно обрабатывать исключительные ситуации.

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

Сценарий транзакции не годится для сложной бизнес - логики.

Диспетчер

Описание. Один системный компонент назначается диспетчером и управляет запуском и завершением других процессов системы и координирует эти процессы. Процессы могут протекать параллельно.

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

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

Паттерны управления, основанные на событиях

Рекомендации. Данный подход эффективен при интеграции подсистем, распределенных на разных компьютерах, которые объединены в сеть.

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

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

Преимущества. Достаточно быстрая реакция системы на происходящие события.

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

5.9.1. Паттерны, обеспечивающие взаимодействие с базой данных

Активная запись (Active Record)

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

Единица работы (Unit Of Work)

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

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

Преимущества. Нет необходимости явно вызывать методы сохранения, достаточно сообщить объекту Единица работы о необходимости фиксации (commit) результатов в базе данных. Вся сложная логика фиксации сосредоточена в одном месте, таким образом, координируется запись в базу данных.

Загрузка по требованию (Lazy Load)

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

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

Коллекция обьектов (Identity Map)

Задача. Требуется гарантировать, что каждый объект будет загружен из базы данных только один раз.

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

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

Множество записей (Record Set)

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

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

Наследование с одной таблицей (Single Table Inheritance)

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

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


При использовании паттерна "Наследование с одной таблицей" формируется следующая таблица


Преимущества. Данный метод прост в реализации и устойчив к модификациям.

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

Наследование с таблицами для каждого класса (Class Table Inheritance)

Описание. Каждой таблице соответствует отдельный класс. Данное отображение является самым простым и прямолинейным вариантом организации наследования (связи между классами и таблицами). При использовании паттерна "Наследование с таблицами для каждого класса" (для примера паттерна "Наследование с одной таблицей") формируются две таблицы:


Недостатки. Для загрузки информации об отдельном объекте приходится осуществлять несколько операций соединения (join), что обычно снижает производительность системы.

Оптимистическая автономная блокировка (Optimistic Offline Lock)

Задача. Бизнес - транзакция содержит несколько системных транзакций, в этом случае СУБД не может гарантировать согласованность записей базы данных. Любая попытка доступа нескольких сеансов к одним и тем же записям грозит нарушением целостности данных и, кроме того, может привести к утрате внесенных изменений.

Решение. Провести проверку, не вступят ли изменения, проведенные одним сеансом в конфликт с изменениями, проведенными другим сеансом (например, сверяется номер версии отдельной записи, сохраненной вместе с состоянием сеанса, с текущим номером версии этой же записи в базе данных). Если проверка прошла успешно, то изменяемые записи блокируются и изменения фиксируются в базе данных. Проверка и фиксация осуществляются в рамках одной системной транзакции, данные останутся согласованными. Срок действия "Оптимистической автономной блокировки" ограничивается той системной транзакцией, в процессе которого она была установлена.

Отображение с помощью внешних ключей

Описание. Требуется организовать в реляционной базе данных отображение связи "один - ко -многим" (в отличие от базы данных для объекта легко реализовать многозначный атрибут - достаточно просто сделать коллекцией значение данного аттрибута).

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

Отображение с помощью таблицы ассоциаций (Association Table Mapping)

Описание. Требуется организовать в реляционной базе данных отображение связи "многие - ко -многим".

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

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

Пессимистическая автономная блокировка (Pessimistic Offline Lock)

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

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

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

Примечание. Альтернативой применению "Пессимистической блокировки" может быть использование длинных системных транзакций.

Поле идентификации (Identity Field)

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

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

Недостатки. Невозможно организовать ссылку на коллекцию обьектов.

Преобразователь данных (Data Mapper)

Описание. При переходе от полей "Шлюза таблицы данных", к полям обьектов "Модели предметной области", приходится выполнять определенные преобразования, которые приводят к усложнению обьектов домена.

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

Преимущества. Полная изоляция бизнес - логики от базы данных.

Cохранение сеанса на стороне клиента (Client Session State)

Задача. Сохранить сведения о сеансе.

Решение. Данные о состоянии сеанса можно сохранять на стороне клиента. При этом клиент передает серверу все сведения о сеансе вместе с каждым запросом. Никаких данных о состоянии сеанса на сервере не хранится. Если есть необходимость хранения числового идентификатора сеанса, то альтернативы данному паттерну не существует.

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

Недостатки. Возникают проблемы безопасности при передаче данных от клиента серверу - передаваемые данные приходится шифровать. Затруднительно использовать данный паттерн при большом объеме информации о сеансе. Часто возникает проблема преобразования формата данных.

Cохранение сеанса на стороне сервера (Server Session State)

Задача. Сохранять сведения о сеансе.

Решение. На клиенте хранится только идентификатор сеанса, а все данные о сеансе хранятся сервером. Для хранения обьектов сеансов на сервере формируется специальная коллекция.

Преимущества. Передается только идентификатор сеанса, а не весь обьем данных о сеансе.

Недостатки. Требуются значительные ресурсы сервера.

Шлюз записи данных (Row Data Gateway)

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

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

Шлюз таблицы данных (Table Data Gateway)

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

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

Тут вы можете оставить комментарий к выбранному абзацу или сообщить об ошибке.

Согласно предложенному принципу классификации паттерны проектирования архитектурные системные паттерны объединены в группы в соответствии с теми задачами, для решения которых они разработаны. Для организации классов или обьектов системы в базовые подструктуры (то есть в подсистемы - соответствующее определение дано в разделе 7.1) используются структурные архитектурные паттерны, см. 4.1. С другой стороны, для обеспечения требуемого системного функционала первостепенное значение имеет адекватная организация взаимодействия отдельных архитектурных элементов системы - этой цели служат управления, см. раздел 4.2.

В свою очередь, паттерны управления разделены на паттерны централизованного управления, 4.2.1 (то есть паттерны, в которых одна из подсистем полностью отвечает за управление, запускает и завершает работу остальных подсистем) и паттерны управления, подразумевающие децентрализованное реагирование на события, 4.2.2, (согласно этим паттернам на внешние события, определённые в разделе 7.3, отвечает соответствующая подсистема.). Также следует упомянуть, что поскольку проектирование взаимодействия той или иной подсистемы с реляционной базой данных (определенной в разделе 7.3) является неотъемлемой частью разработки корпоративных информационных систем, среди паттернов управления выделена большая группа паттернов, описывающих организацию связи с базой данных, см. раздел 4.2.3.

4.1 Структурные паттерны

4.1.1 Репозиторий
Описание Все совместно используемые подсистемами данные хранятся в центральной базе данных, доступной всем подсистемам. Репозиторий является пассивным элементом, а управление им возложено на подсистемы.
Рекомендации Логично использовать, если система обрабатывает большие объёмы данных.
Преимущества Совместное использование больших объёмов данных эффективно, поскольку не требуется передавать данные из одной подсистемы в другие. Подсистема не должна знать, как используются данные в других подсистемах - уменьшается степень связывания.
4.1.2 Клиент/сервер
Описание Данные и процессы системы распределены между несколькими процессорами. Паттерн имеет три основных компонента: набор автономных серверов, (предоставляют сервисы другим подсистемам), набор подсистем - клиентов (которые вызывают сервисы, предоставляемые серверами) и сеть (служит для доступа клиентов к сервисам). Клиенты должны знать имена серверов и сервисов, в то время как серверам не надо знать имена клиентов и их количество. Клиенты получают доступ к сервисам, предоставляемым серверами посредством удаленного вызова процедур.
Рекомендации Данный подход можно использовать при реализации систем, основанных на репозитории, который поддерживается как сервер системы. Подсистемы, имеющие доступ к репозиторию, являются клиентами.
Преимущества Данный паттерн формирует распределенную архитектуру, ее эффективно использовать в сетевых системах с множеством распределенных процессоров В систему легко добавить новый сервер и интегрировать его с остальной частью системы или же обновить сервисы, не воздействуя на другие части системы.
Недостатки При работе серверы и клиенты обмениваются данными, но при большом объеме передаваемых между серверами и клиентами данных могут возникнуть проблемы с пропускной способностью сети.
4.1.3 Обьектно - ориентированный, Модель предметной области (Domain Model), модуль таблицы (Data Mapper)
4.1.4 Многоуровневая система (Layers) или абстрактная машина

На рисунке показаны типичные уровни логической архитектуры системы [ 5].

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

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

4.1.5 Потоки данных (конвейер или фильтр)
Описание Система состоит из функциональных модулей, которые получают на входе данные и преобразуют их некоторым образом в выходные данные (конвейерный подход). Каждый шаг обработки данных реализован в виде преобразования. Преобразования могут выполняться последовательно или параллельно, обработка данных может быть пакетной (пакетный последовательный паттерн) или поэлементной.
Преимущества Возможность повторного использования преобразований, простота в понимании, возможность модификации системы посредством добавления новых преобразований. Данный паттерн прост в реализации как для последовательных, так и для параллельных систем.
Недостатки Необходимость использования некоего общего формата данных, который должен распознаваться всеми преобразованиями. Каждое преобразование либо следует согласовывать со смежными преобразованиями относительно формата преобразовываемых данных, либо необходимо использовать стандартный формат для всех обрабатываемых данных.

4.2 Паттерны управления

4.2.1 Паттерны централизованного управления
4.2.1.1 Вызов - возврат (сценарий транзакции - частный случай).
Описание Вызов программных процедур осуществляется "сверху - вниз", то есть управление начинается на вершине иерархии процедур и через вызовы передается на нижние уровни иерархии.
Рекомендации Применима только в последовательных системах, то есть в таких системах, в которых процессы должны происходить последовательно.
Преимущества Простой анализ потоков управления. Последовательные системы легче проектировать и тестировать.
Недостатки Сложно обрабатывать исключительные ситуации.
Пример Сценарий транзакции можно считать частным случаем паттерна. Сценарий транзакции может быть рассмотрен как способ организации бизнес - логики ("Модель предметной области", см. 4.1.3.) Сценарий транзакции - процедура, которая получает на вход информацию от слоя представления, обрабатывает ее, производя необходимые проверки и вычисления, сохраняет в базе данных и активизирует операции других систем.
4.2.1.2 Диспетчер
Описание Один системный компонент назначается диспетчером и управляет запуском и завершением других процессов системы и координирует эти процессы. Процессы могут протекать параллельно.
Рекомендации Применяется в системах, в которых необходимо организовать параллельные процессы, но может использоваться также и для последовательных систем, в которых- управляющая программа вызывает отдельные подсистемы в зависимости от значений некоторых переменных состояния.
Пример Можно использовать в системах реального времени, где нет чересчур строгих временных ограничений (в так называемых "мягких" системах реального времени).
4.2.2 Паттерны управления, основанные на событиях
4.2.2.2 Управляемый прерываниями
Описание При использовании данного паттерна внешние прерывания регистрируются обработчиком прерываний, а обрабатываются другим системным компонентом.
Рекомендации Используются в системах реального времени со строгими временными требованиями. Данный паттерн может быть скомбинирован с паттерном Диспетчер, см. п. 4.2.1.2: центральный диспетчер управляет нормальной работой системы, а в критических ситуациях используется управление, основанное на прерываниях.
Преимущества Достаточно быстрая реакция системы на происходящие события.
Недостатки При использовании данного подхода система сложна в программировании. При тестировании системы затруднительно имитировать все прерывания. Число прерываний ограничено используемой аппаратурой (после достижения предела, связанного с аппаратными ограничениями, никакие другие прерывания не обрабатываются).
4.2.3 Паттерны, обеспечивающие взаимодействие с базой данных
4.2.3.1 Активная запись (Active Record)

При использовании этого паттерна объект класса "осведомлен" о том, как взаимодействовать с таблицами базы данных.

4.2.3.2 Единица работы (Unit Of Work)
Задача При выполнении операций считывания или изменения обьектов система должна гарантировать, что состояние базы данных останется согласованным. Например, на результат загрузки данных не должны влиять изменения, вносимые другими процессами.
Решение Создается специальный объект, "отслеживающий" изменения, вносимые в базу данных. Данное типовое решение позволяет проконтролировать, какие объекты считываются и какие модифицируются и обслужить операции обновления содержимого базы данных.
4.2.3.3 Загрузка по требованию (Lazy Load)
Задача Требуется загрузить данные из базы данных в оперативную память так, чтобы при загрузке требуемого объекта автоматически загружались и другие связанные с ним объекты, при этом, обьем загружаемых данных не должен быть чрезмерным.
Решение Прерывать процесс загрузки связанных обьектов из базы данных, оставляя при этом соответствующую метку. Это позволит загрузить данные только тогда, когда они действительно потребуются.
4.2.3.4 Коллекция обьектов (Identity Map)
Задача Требуется гарантировать, что каждый объект будет загружен из базы данных только один раз.
Решение Создать специальную коллекцию обьектов, загруженных из базы данных в пределах одной бизнес - транзакции. Таким образом, при получении запроса можно просмотреть эту коллекцию в поисках нужного объекта.
Преимущества Предотвращение повторных загрузок позволяет избежать ошибок и повышает производительность системы.
4.2.3.5 Множество записей (Record Set)
Описание Одна из основополагающих структур данных, имитирующая табличную форму представления содержимого базы данных. Как правило, Множество записей не приходится конструировать самому разработчику, поскольку, как правило, существуют стандартные классы.
Преимущества Удобно для разработчиков, поскольку предоставляет структуру данных, которая хранится в оперативной памяти и соответствует результату выполнения SQL - запроса, в то же время, эта структура данных может быть сгенерирована и использована другими частями системы.
4.2.3.6 Наследование с одной таблицей (Single Table Inheritance)
Задача Поскольку SQL не предоставляет стандартных инструментов поддержки наследования, требуется создать специальный аппарат отображения в базе данных иерархии наследования.
Решение Все поля всех классов наследования отображаются в одной и той же таблице. Например, требуется отобразить структуру

При использовании паттерна "Наследование с одной таблицей" формируется следующая таблица

Распределённые приложения — главный элемент современной индустрии разработки ПО. Они имеют решающее значение для облачных сервисов хранения данных и позволяют веб-приложениям с огромной аудиторией оставаться реактивными. Для того чтобы эффективно проектировать эти системы, программисты используют фундаментальные блоки — паттерны распределённых систем.

Мы рассмотрим пять архитектур распределённых систем, их плюсы, минусы и области применения.

Шаблоны проектирования простым языком. Часть первая. Порождающие шаблоны

Что такое паттерн распределённой системы?

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

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

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

Эти паттерны широко используются в архитектуре крупномасштабных облачных вычислений и систем масштабируемых микросервисов.

Типы паттернов распределённых систем

Большинство паттернов распределённых систем попадает в одну из трёх категорий, в зависимости от функциональности с которой они работают:

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

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

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

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

Область применения

CQRS отлично подходит для приложений, интенсивно использующих данные, например систем управления базами данных SQL или NoSQL. Также паттерн используется для архитектур микросервисов с большим объемом данных. Он прекрасно подходит для приложений, сохраняющих состояние благодаря разделению на писателя и читателя.

2. Двухфазная фиксация (2PC)

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

2PC гарантирует, что одновременно может работать только одна служба, что делает процесс более устойчивым и последовательным, чем CQRS.

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

Область применения

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

3. Saga

Saga — это асинхронный паттерн не использующий центр управления. Сервисы здесь сами взаимодействуют между собой. Эта особенность позволяет избавиться от недостатков упомянутых выше паттернов.

Для связи между сервисами в Saga используется шина событий. Шина передаёт запросы между службами, и каждая участвующая служба создает локальную транзакцию. Затем участвующие службы выдают событие для получения другими службами. Все другие службы прослушивают события. Первая служба, получившая событие, выполнит необходимое действие. Если этой службе не удается выполнить действие, оно отправляется в другие службы.

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

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

Область применения

Этот паттерн распределённой системы хорошо подходит для задач, которым требуется масштабируемая беcсерверная архитектура, способная обрабатывать много запросов одновременно. AWS использует подобные решения в AWS Step Functions и AWS Lambda, и других продуктах.

4. Реплицированные сервисы с распределением нагрузки (RLBS)

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

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

RLBS часто используется с Azure Kubernetes, которая представляет собой технологию оркестровки контейнеров с открытым исходным кодом, разработанную Microsoft, которая предлагает автоматическое масштабирование служб в зависимости от воркфлоу.

  • Стабильная производительность с точки зрения конечного пользователя.
  • Быстрое восстановление после сбоев.
  • Высокая масштабируемость через увеличение числа сервисов.
  • Отличная многопоточность.
  • Нестабильная производительность, зависящая от алгоритма балансировки.
  • Управление сервисами требует много ресурсов.

Область применения

RLBS отлично подходит для систем, с которыми пользователи взаимодействуют напрямую. Нагрузка на эти системы в течение дня изменяется, поэтому требуется низкая задержка, например Netflix или Amazon Prime.

5. Шардинг

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

Шардинг сервисов обычно используется для создания сервисов с поддержкой состояния, потому что объём состояния часто слишком большой для одного stateless контейнера. Шардинг позволяет масштабировать отдельные элементы под размер состояния.

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

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

Область применения

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

Что дальше?

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

Паттерны в чистом виде встречаются довольно редко и при изучении паттернов, особенно на ранних этапах, важны не столько сами паттерны, сколько понимание механизмов (тактик), с помощью которых они реализуются. В этой статье я хотел бы описать один из таких механизмов (управление зависимостями), который используется в паттернах Observer и Mediator, но который часто упускается из внимания. Если ты только начинаешь изучать паттерны, то добро пожаловать под кат.

Управление зависимостями

Начнём с утверждения: если класс A зависит от класса B, то, не меняя поведения, можно переписать код так, что класс B будет зависеть от класса A или ввести ещё один класс C таким образом, что классы A и B будут независимы, а класс C будет связывать и зависеть от классов A и B.


Один класс зависит от другого, если он обращается к его полям или методам. Поля легко переносятся из одного класса в другой, поэтому остановимся подробнее на методах. Допустим, класс B содержит метод Print, который выводит текущую дату в консоль, а класс А вызывает этот метод.


Таким образом класс A зависит от класса B. Чтобы вывернуть эту зависимость, вместо вызова метода Print напрямую, сгенерируем событие. Теперь класс А ничего не знает о классе B, а класс B может подписаться на событие класса A. Т.е. класс B будет зависеть от класса A.


Поведение кода не меняется, а в вызывающем методе меняется только порядок инициализации объектов и передача зависимостей в конструктор.

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


Теперь классы A и B полностью независимы, каждый выполняет свою задачу и ничего не знает о других классах. Логика по взаимодействию между объектами уходит в новый класс. Только класс C знает в ответ на какие события и при каких условиях должны вызываться методы класса B. Таким образом, класс C становится медиатором.

Итоги: Борьба со сложностью системы

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

Паттерн Observer уменьшает связанность за счёт обращения зависимостей. Он хорошо применим, когда есть несколько источников событий и много слушателей, которые добавляются динамически. Другим хорошим примером использования этого паттерна является реактивное программирование, когда изменение состояния одного объекта приводит к изменению состояния всех зависимых от него объектов и так далее.



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

Опасным подводным камнем при использовании паттернов Observer и Mediator является наличие циклических ссылок, когда события из одного класса, проходя по цепочки объектов, приводят к генерированию этого же события ещё раз. Эта проблема тяжело разрешима и заметно усложняет использование паттернов.

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

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