2016-01-23 2 views
1

В последние дни я исследовал, как стиль Node.js на основе событий может обрабатывать гораздо более параллельный запрос, чем классический подход многопоточности. В конце речь идет о меньшем объеме памяти и контекстных переключателях, поскольку Node.js использует только пару потоков (один поток V8 и кучу рабочих потоков C++ плюс основной поток libuv).Какую роль играет двигатель V8 в Node.js?

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

Вот как я понимаю работы Node.js.

Мне было интересно, что дает Node.js возможность обрабатывать HTTP-запросы. Основываясь на том, что я читал до сих пор, я понимаю, что libuv есть кто делает эту работу:

Рукоятки представляют долгоживущие объекты, способные выполнять определенные операции во время активной. Некоторые примеры: дескриптор подготовки получает свой обратный вызов , который вызывается один раз после каждой итерации цикла, когда он активен, и . Администратор дескриптора TCP получает свой обратный вызов соединения каждый раз, когда есть новое соединение .

enter image description here

Таким образом, поток, который ожидает входящий запрос HTTP является основным-нить libuv, которая выполняет цикл libuv событий.

Так что, когда мы пишем

const http = require('http'); 

const hostname = '127.0.0.1'; 
const port = 1337; 

http.createServer((req, res) => { 
    res.writeHead(200, { 'Content-Type': 'text/plain' }); 
    res.end('Hello World\n'); 
}).listen(port, hostname,() => { 
    console.log(`Server running at http://${hostname}:${port}/`); 
}); 

... Я помещаю в libuv обратного вызова, которая будет выполнена в двигателе V8, когда приходит запрос?

Порядок событий будет тогда

  1. TCP-пакет прибывает
  2. ОС создает событие и посылает в цикл обработки событий
  3. Цикл событий обрабатывает событие и создает событие V8

Если я выполняю код блокировки внутри анонимной функции, которая обрабатывает запрос, я блокирую поток V8.

Чтобы избежать этого, мне нужно выполнить неблокирующий код, который будет выполнен в другом потоке. Я предполагаю, что это «другой поток» является главной нитью libuv где

сети I/O всегда выполняется в одном потоке, поток каждого контура в

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

Epoll на Linux, Kqueue на OSX и других BSDs, порты событий на SunOS и IOCP на Windows,

Я также полагаю, что http.request использует libuv для achive это.

Similary, если мне нужно сделать какой-то файл ввод/вывод без блокировки V8 нити
Я буду использовать FileSystem модуль Node. На этот раз основной поток libuv не может справиться с этим неблокирующим способом, поскольку ОС не предлагает эту функцию.

В отличие от сети I/O, нет конкретной платформы файл ввода/вывода примитивов libuv мог положиться, поэтому в настоящее время подход заключается в запуске блокирующую операций ввода/вывода в пуле потоков.

В этом случае необходим классический пул потоков, чтобы не блокировать цикл событий libuv.

Теперь, если мне нужно запросить базу данных, то вся ответственность за блокировку ни потока V8, ни потока libuv находится в руках разработчика драйвера. Если водитель не использует libuv, он заблокирует двигатель V8.

Вместо этого, если он использует libuv, но базовая база данных не имеет асинхронных возможностей, то она будет block a worker thread.

И, наконец, если база данных предоставляет возможности async, она блокирует поток базы данных. (В этом случае я мог вообще избегать libuv и вызывать драйвер непосредственно из потока V8)

Если эти выводы правильно описывают, хотя и упрощенным образом, способы, с помощью которых libuv и V8 работают вместе в Node.js, Я не вижу преимуществ использования V8, потому что мы могли бы выполнять всю работу в libuv напрямую (если только целью не является предоставление разработчику языка, который упрощает запись кода на основе событий).

ответ

0

Из чего я знаю, разница в основном асинхронная ввода-вывода. В традиционных серверах с технологией «за каждый запрос» или «поток за запрос» ввод-вывод, в первую очередь сетевой ввод-вывод, является традиционно синхронным вводом-выводом. Node.js использует меньше потоков, чем Apache или что-то еще, и может обрабатывать трафик главным образом потому, что использует асинхронный сетевой ввод-вывод.

Node.js нуждается в V8, чтобы фактически интерпретировать JS-код и превратить его в машинный код. Libuv необходим для реального ввода-вывода. Я не знаю намного больше :)

0

Отличная статья о node.js V8 двигатель: How JavaScript works: inside the V8 engine + 5 tips on how to write optimized code. Он объяснил многие глубоко детализированные аспекты двигателя и некоторые отличные рекомендации при его использовании.

Проще говоря, то, что V8 engine (и другие javascript engines) действительно должно выполнить код javascript. Тем не менее, V8 engine получает высокопроизводительное исполнение по сравнению с другими.

V8 переводит код JavaScript в более эффективный машинный код вместо с использованием интерпретатора. Он компилирует код JavaScript в машинный код при выполнении с помощью компилятора JIT (Just-In-Time) ...

0

I/O неблокирует и асинхронно через libuv, в основе которого лежат примитивы ОС, такие как epoll или аналогичные, в зависимости от платформы, чтобы сделать i/o не блокируемым. Цикл событий Nodejs получает событие в очереди, когда происходит событие на fd (tcp socket в качестве примера)

Смежные вопросы