Как мне написать неблокирующий код в Node.js ?

#javascript #node.js #blocking #eventemitter

#javascript #node.js #блокировка #eventemitter

Вопрос:

Я могу написать неблокирующий ввод-вывод в Node.js очень просто. Это то, для чего настроена вся библиотека.

Но любое выполненное вычисление блокируется. Любое сообщение, проходящее через источники событий, блокируется.

Например, исходящие события разрешаются немедленно и, таким образом, блокируют:

 var e = new process.EventEmitter;
e.on("foo", function() {
    console.log("event");
});
process.nextTick(function() {
    console.log("next tick");
});
setTimeout(function() {
    console.log("timeout");
}, 0);
e.emit("foo");

> event
> next tick
> timeout
  

Помимо переноса вызовов в nextTick , как мне сделать код неблокирующим?

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

Как мне написать свой код неблокирующим способом?

И когда у меня есть неблокирующий код, как мне масштабировать его для нескольких процессов?

Одним из вариантов является ожидание завершения работы API подпроцесса WebWorker.

Комментарии:

1. Во-первых, 90% вашего «Вопроса» на самом деле не вопрос, это скорее проблема с библиотекой событий узла, это должно быть поднято либо как запрос функции, либо как возможная ошибка на github, что касается вашего небольшого вопроса, я бы создал вопрос, посвященный этой теме, а не сжимал его в этом.

2. @RobertPitt спасибо, что указали, что вопрос был сформулирован неудачно. я его скорректировал. Я мог бы также упомянуть об этом на github.

3. Это немного лучше, спасибо.

Ответ №1:

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

Если вы разделите свою обработку на этапы, используя process.nextTick , как это делается с setTimeout(fn, 0) на стороне клиента, чтобы избежать блокировки пользовательского интерфейса, вы могли бы распределить свою рабочую нагрузку на более длительный промежуток времени, предоставляя некоторое пространство для запуска других функций.

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

child_process.fork() был добавлен в версию 0,5 несколько дней назад. Это упрощает создание дочернего процесса и взаимодействие — не совсем web workers API, но близко, смотрите URL
https://github.com/joyent/node/blob/master/doc/api/child_process.markdown.

Комментарии:

1. Это именно то, что я показал в своем фрагменте. Обработка событий блокируется. Мой вопрос в том, как мне выполнить неблокирующую передачу сообщений для оптимизации параллелизма? Я думаю, что вызов process.nextTick — лучший способ.

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

3. Javascript по-прежнему однопоточный, и ваши функции будут «блокироваться» независимо от их размещения. Другие задачи также будут заблокированы, вы просто измените их порядок. Если вы разделите свою обработку на этапы, как это делается на стороне клиента, чтобы избежать блокировки пользовательского интерфейса, вы можете распределить тот же объем работы на более длительное время — тогда вы могли бы получить немного лучший параллелизм, но в обмен на более длительное время отклика. Это не то, что node.js примерно. Преимущества неблокирующего кода заключаются в том, что он не простаивает в ожидании ответов, а не в том, что он избегает всех вычислений.

4. @RicardoTomasi этот последний комментарий действительно подводит итог моим неправильным представлениям. Если вы можете отредактировать ответ, чтобы объяснить мое заблуждение, я приму его

5. Отредактировано @Raynos. также добавлено упоминание о новом .fork() API, вы должны взглянуть на него.

Ответ №2:

В JavaScript нет реальной многопоточности, и это то, что вам нужно, чтобы сделать вызов неблокирующим. Единственное, о чем я могу думать, это веб-работники:https://developer.mozilla.org/en/Using_web_workers

Комментарии:

1. Опять же, я не программировал на JS в течение нескольких лет, поэтому я могу ошибаться.

2. обратные вызовы на process.nextTick неблокирующие. Вы можете использовать цикл событий для написания неблокирующего кода, но отправители событий не используют цикл событий. Я не знаю, как использовать цикл событий.