Модель реактора

Тип шаблона проектирования программного обеспечения

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

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

Благодаря балансу простоты и масштабируемости реактор стал центральным архитектурным элементом в нескольких серверных приложениях и программных фреймворках для сетей . Существуют также производные, такие как мультиреактор и проактор, для особых случаев, когда требуется еще большая пропускная способность, производительность или сложность запроса. [1] [2] [3] [4]

Обзор

Практические соображения относительно модели клиент-сервер в больших сетях, такие как проблема C10k для веб-серверов , были первоначальной мотивацией для шаблона реактора. [5]

Наивный подход к обработке запросов на обслуживание от многих потенциальных конечных точек, таких как сетевые сокеты или файловые дескрипторы , заключается в прослушивании новых запросов из цикла событий, а затем немедленном чтении самого раннего запроса. После того, как весь запрос будет прочитан, его можно обработать и переслать дальше, напрямую вызвав соответствующий обработчик. Полностью «итеративный» сервер, подобный этому, который обрабатывает один запрос от начала до конца за итерацию цикла событий, логически допустим. Однако он отстанет, как только получит несколько запросов в быстрой последовательности. Итеративный подход не может масштабироваться, поскольку чтение запроса блокирует единственный поток сервера до тех пор, пока не будет получен полный запрос, а операции ввода-вывода обычно намного медленнее других вычислений. [2]

Одной из стратегий преодоления этого ограничения является многопоточность: путем немедленного разделения каждого нового запроса в его собственный рабочий поток, первый запрос больше не будет блокировать цикл событий, который может немедленно итерировать и обрабатывать другой запрос. Такая конструкция «поток на соединение» масштабируется лучше, чем чисто итеративная, но она все еще содержит множество неэффективностей и будет испытывать трудности после определенной точки. С точки зрения базовых системных ресурсов , каждый новый поток или процесс налагает накладные расходы на память и время обработки (из-за переключения контекста ). Фундаментальная неэффективность каждого потока, ожидающего завершения ввода-вывода, также не устранена. [1] [2]

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

  1. Сохраните однопоточный обработчик событий; многопоточность приводит к накладным расходам и сложности, не решая при этом реальную проблему блокировки ввода-вывода.
  2. Использовать механизм уведомления о событиях для демультиплексирования запросов только после завершения ввода-вывода (чтобы ввод-вывод фактически не блокировался)
  3. Зарегистрируйте обработчики запросов как обратные вызовы с обработчиком событий для лучшего разделения задач.

Объединение этих идей приводит к шаблону реактора, который сочетает преимущества однопоточности с высокой пропускной способностью и масштабируемостью. [1] [2]

Использование

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

Однако шаблон реактора имеет ограничения, основным из которых является использование обратных вызовов, что затрудняет анализ и отладку программ , что является общей проблемой для проектов с инвертированным управлением . [1] Более простые подходы «поток на соединение» и полностью итеративные подходы позволяют избежать этого и могут быть приемлемыми решениями, если масштабируемость или высокая пропускная способность не требуются. [a] [ необходима цитата ]

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

Приложения

Шаблон реактора (или его вариант) нашел применение во многих веб-серверах, серверах приложений и сетевых фреймворках:

Структура

Реактивное приложение состоит из нескольких подвижных частей и будет полагаться на некоторые механизмы поддержки: [1]

Ручка
Идентификатор и интерфейс для конкретного запроса с вводом-выводом и данными. Часто это принимает форму сокета, файлового дескриптора или подобного механизма, который должен предоставляться большинством современных операционных систем.
Демультиплексор
Уведомитель событий, который может эффективно отслеживать состояние дескриптора, а затем уведомлять другие подсистемы о соответствующем изменении состояния (обычно дескриптор ввода-вывода становится «готовым к чтению»). Традиционно эта роль выполнялась системным вызовом select() , но более современные примеры включают epoll , kqueue и IOCP .
Диспетчер
Фактический цикл событий реактивного приложения. Этот компонент поддерживает реестр допустимых обработчиков событий, а затем вызывает соответствующий обработчик при возникновении события.
Обработчик событий
Также известный как обработчик запросов, это конкретная логика для обработки одного типа запроса на обслуживание. Шаблон реактора предполагает динамическую регистрацию их в диспетчере в качестве обратных вызовов для большей гибкости. По умолчанию реактор не использует многопоточность, а вызывает обработчик запросов в том же потоке, что и диспетчер.
Интерфейс обработчика событий
Абстрактный интерфейсный класс, представляющий общие свойства и методы обработчика событий. Каждый конкретный обработчик должен реализовать этот интерфейс, в то время как диспетчер будет работать с обработчиками событий через этот интерфейс.

Варианты

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

Одной из основных модификаций является вызов обработчиков событий в их собственных потоках для большего параллелизма. Запуск обработчиков в пуле потоков , вместо запуска новых потоков по мере необходимости, еще больше упростит многопоточность и минимизирует накладные расходы. Это делает пул потоков естественным дополнением к шаблону реактора во многих вариантах использования. [2]

Другой способ максимизировать пропускную способность — частично повторно ввести подход сервера «поток на соединение» с реплицированными диспетчерами/циклами событий, работающими одновременно. Однако вместо количества соединений настраивается количество диспетчеров в соответствии с доступными ядрами ЦП базового оборудования.

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

Для особо сложных сервисов, где синхронные и асинхронные требования должны быть объединены, еще одной альтернативой является шаблон proactor. Этот шаблон сложнее, чем реактор, со своими собственными инженерными деталями, но он все еще использует подкомпонент реактора для решения проблемы блокировки ввода-вывода. [3]

Смотрите также

Похожие шаблоны:

Примечания

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

Ссылки

  1. ^ abcdefghijk Шмидт, Дуглас К. (1995). "Глава 29: Реактор: поведенческий шаблон объекта для демультиплексирования и диспетчеризации дескрипторов для синхронных событий" (PDF) . В Коплиене, Джеймсе О. (ред.). Языки шаблонов проектирования программ . Том 1 (1-е изд.). Эддисон-Уэсли. ISBN 9780201607345.
  2. ^ abcdefg Девресс, Адриен (20 июня 2014 г.). "Эффективный параллельный ввод-вывод на многоядерных архитектурах" (PDF) . 2-я тематическая школа ЦЕРН по вычислениям . ЦЕРН. Архивировано (PDF) из оригинала 8 августа 2022 г. . Получено 14 сентября 2023 г. .
  3. ^ abcde Эскофье, Клемент; Финнеган, Кен (ноябрь 2021 г.). "Глава 4. Принципы проектирования реактивных систем" . Реактивные системы на Java . O'Reilly Media. ISBN 9781492091721.
  4. ^ abc Гарретт, Оуэн (10 июня 2015 г.). «Внутри NGINX: как мы проектировали производительность и масштабируемость». NGINX . F5, Inc. Архивировано из оригинала 20 августа 2023 г. Получено 10 сентября 2023 г.
  5. ^ Кегель, Дэн (5 февраля 2014 г.). «Проблема C10k». Dan Kegel's Web Hostel . Архивировано из оригинала 6 сентября 2023 г. Получено 10 сентября 2023 г.
  6. ^ Бонер, Йонас (15 июня 2022 г.). «Реактивные паттерны: 3. Изолировать мутации». Реактивные принципы . Получено 20 сентября 2023 г.
  7. ^ "Сетевое программирование: написание сетевых и интернет-приложений" (PDF) . Проект POCO . Applied Informatics Software Engineering GmbH. 2010. стр.  21–22 . Получено 20 сентября 2023 г.
  8. ^ Стоянчев, Россен (9 февраля 2016 г.). «Реактивная весна». Spring.io . Получено 20 сентября 2023 г. .
  9. ^ "Обзор реактора". twisted.org . Получено 28 июля 2024 г. .

Конкретные области применения:

  • Алексеев, Эндрю (30 марта 2012 г.). "Глава 14: nginx". В Браун, Эми; Уилсон, Грег (ред.). Архитектура приложений с открытым исходным кодом . Том 2. Lulu.com. ISBN 9781105571817.

Примеры реализаций:

  • Сеть APR и модель реактора
  • Архитектура высокомасштабируемого сервера на базе NIO
Взято с "https://en.wikipedia.org/w/index.php?title=Reactor_pattern&oldid=1237319170"