Подтвердить что ты не робот

Node.js Контур события

Является ли цикл событий ввода/вывода Node.js одно- или многопоточным?

Если у меня несколько процессов ввода-вывода, node помещает их во внешний цикл событий. Они обрабатываются в последовательности (быстрее всего) или обрабатывают цикл событий для одновременного их обработки (... и в каких ограничениях)?

4b9b3361

Ответ 1

Цикл событий

Цикл событий Node.js выполняется под одним потоком, это означает, что код приложения, который вы пишете, оценивается в одном потоке. Сам Nodejs использует множество потоков под libuv, но вам никогда не приходится иметь дело с ними при написании кода nodejs.

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

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

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

Подробнее о цикле событий

Ограничения

Из-за цикла событий node не нужно запускать новый поток для каждого входящего tcp-соединения. Это позволяет node обслуживать сотни тысяч запросов одновременно, пока вы не вычисляете первые 1000 простых чисел для каждого запроса.

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

Если вы хотите делать тяжелые вещи CPU, вы должны просто делегировать его другому процессу, который может выполнять операцию привязки к процессору более эффективно, или вы можете записать его как node native add on.

Подробнее о вариантах использования

Управляющий поток

Чтобы управлять написанием многих обратных вызовов, вы, вероятно, захотите использовать библиотеку потока управления. Я считаю, что в настоящее время это самая популярная библиотека, основанная на обратном вызове:

Я использовал обратные вызовы, и они в значительной степени сводили меня с ума, у меня было гораздо больше опыта с использованием Promises, bluebird - очень популярная и быстрая библиотека обещаний:

Я обнаружил, что это очень чувствительная тема в сообществе node (обратные вызовы vs promises), поэтому, во что бы то ни стало, используйте то, что, по вашему мнению, будет работать лучше всего для вас лично. Хорошая библиотека потока управления также должна давать вам трассировки стека асинхронного сканирования, это действительно важно для отладки.

Процесс Node.js завершится, когда последний обратный вызов в цикле событий завершит его путь выполнения и не зарегистрирует никаких других обратных вызовов.

Это не полное объяснение, я советую вам проверить следующий поток, он довольно обновлен:

Как мне начать с Node.js

Ответ 2

Из ответа Виллема:

Цикл событий Node.js выполняется под одним потоком. Для каждого вызова ввода/вывода требуется зарегистрировать обратный вызов. Каждый вызов ввода-вывода также немедленно возвращается, это позволяет выполнять несколько операций ввода-вывода параллельно без использования потоков.

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

Node.js не магически обрабатывает все эти асинхронные вызовы только одним потоком и по-прежнему не разблокирует этот поток. Он внутренне использует движок Google V8 и библиотеку libuv (написанную на языке С++), которая позволяет ему делегировать некоторую потенциальную асинхронную работу другим рабочим потокам (вроде как поток потоков, ожидающий там, где любая работа должна быть делегирована из мастера node поток). Затем, когда эти потоки завершают выполнение, они вызывают их обратные вызовы, и именно так цикл цикла знает о завершении выполнения рабочего потока.

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

Ниже приведен хороший пост, если кто-то заинтересован: Когда используется пул потоков?