Представляет ли nodejs шаблон проектирования Reactor или Proactor? - PullRequest
0 голосов
/ 24 июня 2019

Многие статьи онлайн демонстрируют nodejs как пример схемы реактора. Разве это не проактор?

Насколько я понимаю, разница между ними такова:

  1. реактор обрабатывает события в одном потоке (синхронно) ,
  2. обработчик событий обрабатывает несколько потоков (асинхронно) с обратными вызовами завершения .

Например, в этой статье :

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

Разве это не определение проактора?

Ответы [ 2 ]

1 голос
/ 25 июня 2019

Я не был знаком с шаблоном проектирования Proactor.Прочитав немного об этом, я думаю, что понимаю вашу путаницу.

Во многих статьях онлайн демонстрируется nodejs в качестве примера схемы реактора

Это правда.

Разве это не на самом деле определение проактора?

Это также верно.

Разница в вашей точке зрения.

Внутренне,Цикл событий узла является блокирующим вызовом (по иронии судьбы).Это просто самый эффективный способ использования неблокирующего ввода-вывода.Различные ОС имеют разные функции, чтобы запросить ОС, чтобы разбудить ваш процесс, если произойдет одно или несколько событий в списке интересующих вас событий.Из-за требований POSIX существует кроссплатформенный API, который поддерживают все современные операционные системы: select().Node.js фактически использует libuv, который автоматически выбирает правильный API во время компиляции, в зависимости от целевой платформы.Но для целей этого ответа мы собираемся сосредоточиться на select().Итак, давайте посмотрим на select () :

    numberOfEvents = select(numberOfWaits, read, write, err, timeout);

Функциональные блоки select() на срок до timeout миллисекунд или что-то происходит с файлами / сокетами чтения, записи или ошибками,Всего лишь с одной функцией ОС обеспечивает достаточную функциональность для реализации большей части node.js от таймеров, таких как setTimeout() и setInterval(), до прослушивания сетевых сокетов.При использовании select() цикл обработки событий выглядит примерно так:

// Pseudocode:

while(1) {
    evaluateJavascript();
    timeout = calculateTimers();
    events = select(n, read, write, err, timeout);
    if (events > 0 || timersActive()) {
        getCallbacks(events, read, write, err, timers());
    }
}

Это в основном шаблон проектирования Reactor.

Однако узел скрывает это в своей реализации.То, что он предоставляет программистам Javascript, представляет собой набор API, который регистрирует обратные вызовы и вызывает эти обратные вызовы, когда происходит событие.Это частично исторически (API-интерфейсы браузеров были разработаны таким образом) и частично практично (это гораздо более гибкая архитектура - почти все структуры GUI от GTK до wxWindows до .Net работают таким образом).

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

Таким образом, сам node.js является примером шаблона проектирования Reactor.

Программы Javascript, написанные в node.js, являются примерами шаблона проектирования Proactor.

0 голосов
/ 25 июня 2019

Различие не имеет ничего общего с многопоточностью.Это выглядит следующим образом:

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

Узел имеет API обоих типов, например stream.ReadableStream # readable / stream.ReadableStream # read - это интерфейс Reactor, а fs.readFile - это Proactor.

...