Однопоточная и Event Loop в Node.js

Прежде всего, я начинаю пытаться понять, что такое Node. У меня есть два вопроса.

Первый вопрос
Из статьи Феликса он сказал: "Одновременно может быть только один обратный вызов. Пока этот обратный вызов не завершит выполнение, все остальные обратные вызовы должны ждать в очереди".

Затем рассмотрим следующий код (скопированный с официального сайта nodejs)

var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(8124, "127.0.0.1");

Если два клиентских запроса принимаются одновременно, это означает следующий рабочий процесс:

  • Получено первое событие запроса HTTP, получено второе событие запроса.
  • Как только будет получено первое событие, будет выполняться функция обратного вызова для первого события.
  • В то время как функция обратного вызова для второго события должна ждать.

Я прав? Если я прав, то как Node.js контролировать, если тысячи запросов клиентов находятся в очень короткой продолжительности.

Второй вопрос
Термин "Event Loop" в основном используется в теме Node.js. Я понял "Event Loop" следующим образом: http://www.wisegeek.com/what-is-an-event-loop.htm;

Цикл события - или основной цикл - это конструкция внутри программ, которые контролирует и отправляет события после начального события.

Первоначальное событие может быть любым, включая нажатие кнопки на клавиатуры или нажатием кнопки в программе (в Node.js, я думаю, что начальными событиями будут HTTP-запрос, запросы db или доступ к файлу ввода-вывода).

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

У меня конфликт со вторым абзацем, особенно фраза " повторяет процесс снова и снова". Я признал, что вышеупомянутый код http.createServer из приведенного выше вопроса является абсолютно "циклом событий", поскольку он многократно прослушивает события HTTP-запроса.

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

database.query("SELECT * FROM table", function(rows) {
  var result = rows;
});

Пожалуйста, позвольте мне услышать ваши мнения и ответы.

Ответ 1

Ответьте, ваша логика верна: второе событие будет ждать. И будет выполняться до тех пор, пока не появятся его обратные вызовы.

Кроме того, помните, что в техническом мире нет такой вещи, как "одновременно". Все имеет очень специфическое место и время.

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

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

Тем не менее, он позволяет создавать несколько потоков (как child_process) через cluster, что расширяет еще больше возможностей.

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

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

В случае с http.createServer вы связываете обратный вызов как ответ на запросы. Все операции сокета и операции ввода-вывода будут происходить за кулисами, а также квитирование HTTP, разбор заголовков, запросов, параметров и т.д. Как только это происходит за кулисами, и работа выполнена, он будет хранить данные и будет вызывать обратный вызов в цикле событий с некоторыми данными. Когда цикл событий будет свободен и придет время, он выполнит в контексте приложения node.js ваш обратный вызов с данными из-за кулис.

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

Честно говоря, все, что вам нужно с node.js, заключается в понимании концепции, но не в реализации событий. И лучший способ сделать это - эксперимент.

Ответ 2

1) Да, вы правы.

Это работает, потому что все, что вы делаете с node, в первую очередь связано с I/O.

Когда приходит новый запрос (событие), он помещается в очередь. Во время инициализации node выделяет ThreadPool, который отвечает за появление потоков для обработки привязки ввода-вывода, таких как вызовы сети/сокета, база данных и т.д. (Это не блокирует).

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

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

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

2) Вы правы, снова.

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

В частности, Nodejs реализуется с libuv.

Интересно для читать.

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

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