Node JS Архитектура процессора - PullRequest
0 голосов
/ 08 февраля 2019

Я пытался найти решение своей проблемы, связанной с архитектурой узла js.

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

Но мойпроблема в том, как работает процессор, работающий за ним, работает ли он синхронно и в приоритетном порядке?или он работает с несколькими запросами одновременно на одном ядре.

Попытался проверить это, создав два API. В первом API я создал цикл while, тогда как во втором API я создал ответ hello world.

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

Так что можноЯ говорю, что процессор узла js будет работать в синхронном порядке, но не параллельно?

Так что все запросы должны будут ждать в очереди для завершения предыдущих запросов?

Ответы [ 2 ]

0 голосов
/ 08 февраля 2019

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

В этот момент другое событие может запустить и запустить другой обработчик событий, и снова никакой другой Javascript не может быть запущен, пока этот обработчик не вернется обратно в систему.

Это верно для ВСЕГО Javascript, который запускает node.js.

Аааа, но не все, что вы делаете в node.js, на самом деле является Javascript.Предположим, у вас есть два простых таймера:

console.log("A");
setTimeout(function() {
   console.log("B");
   fs.readFile("smallfile.txt", function(err, data) {
       console.log("C");
   });
   console.log("H");
}, 1000);

console.log("D");

setTimeout(function() {
   console.log("E");
   fs.readFile("bigfile.txt", function(err, data) {
       console.log("F");
   });
   console.log("I");
}, 1000);

console.log("G");

Это позволит войти в консоль

A
D
G
B
H
E
I
C
F

Давайте обсудим, почему это будет сделано.

A очевидно, это первое утверждение.

Затем код вызывает setTimeout(), который не является блокирующим и асинхронным.Таким образом, все, что он делает, это намечает таймер на некоторое время в будущем и затем немедленно возвращается.Обратный вызов setTimeout() не будет готов к вызову в течение 1000 мс, поэтому он не будет вызван прямо сейчас.

Итак, после следующего вызова setTimeout() мы выполняем console.log("D");

Затем он выполняет следующий setTimeout(), который снова просто планирует таймер на 1000 мсек и немедленно возвращается.

Затем он выполняет console.log("G");.

В этот момент он возвращает управление обратно интерпретатору JS, и некоторое время ему больше нечего делать.

Затем, примерно через 1000 мс, первый таймер setTimeout() вставляет событие таймера в очередь событий, и, поскольку интерпретатор JS не выполняет какой-либо другой Javascript, он захватывает это событие и запускает обратный вызов JS, связанный с этим событием.Это сразу записывает console.log("B");.

Затем он вызывает fs.readFile("smallfile.txt", ...).Это опять-таки неблокирующее и асинхронное, поэтому все, что он делает, это говорит базовой реализации модуля fs собственного кода, чтобы он прочитал все данные из этого файла и затем немедленно вернулся.Затем он запускается console.log("H");.На этом этапе это делается с помощью этого обработчика событий и возвращает управление обратно интерпретатору.

Между тем второе событие setTimeout() готово, поэтому интерпретатор JS извлекает это событие из очереди событий и вызывает соответствующий обратный вызовс этим.

Он запускается console.log("E"); и затем вызывает fs.readFile ("bigfile.txt", ...) . This is again non-blocking and asynchronous so all it does is tell the underlying native code fs module implementation to go read all the data from this file and then returns immediately. It then runs console.log ("I"); `.На этом этапе это делается с помощью этого обработчика событий и возвращает управление обратно интерпретатору.

Через некоторое время fs.readFile("smallfile.txt", ...) завершает работу и вставляет событие в очередь событий.Поскольку интерпретатору JS больше нечего делать, он извлекает это событие и запускает обратный вызов, связанный с ним, и мы видим результаты console.log("C").Затем он завершается и возвращает управление обратно интерпретатору.

Через некоторое время fs.readFile("bigfile.txt", ...) завершает работу и вставляет событие в очередь событий.Поскольку интерпретатору JS больше нечего делать, он извлекает это событие и запускает обратный вызов, связанный с ним, и мы видим результаты console.log("F").Затем он завершается и возвращает управление обратно интерпретатору.

На этом этапе все сделано.

Надеемся, вы сможете увидеть, как асинхронные операции (реализованные в собственном коде могут выполняться параллельно с выполнением Javascriptиспользуя другие ядра ЦП), и они синхронизируются с выполнением Javascript путем помещения событий в очередь событий.Когда JS-интерпретатор завершает работу с обработчиком событий, он может искать в очереди событий следующее событие, которое нужно запустить, или, если ничего не происходит, переходить в спящий режим, пока следующее событие не будет вставлено в очередь событий.

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

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

0 голосов
/ 08 февраля 2019

С моей точки зрения, дело в том, что ответ на этот вопрос не так прост.

1) Если мы говорим о ExpressJS, то да, он работает синхронно

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

Различные модули в NodeJ ведут себя по-разному - от синхронных до асинхронных.NodeJS V8 на основе VUlibs, которые на самом деле являются библиотеками на основе C ++, и большинство из этих библиотек используют механизм потоков.Например, криптомодуль может выполнять выполнение асинхронно до некоторой степени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...