Потоки Node.js, вы можете ошибаться

Node.js внешний интерфейс JavaScript V8
Потоки Node.js, вы можете ошибаться
本文代码运行环境
系统:MacOS High Sierra
Node.js:10.3.0

Node.js является однопоточным, поэтому количество потоков после запуска Node.js равно 1?

Ответ. Количество потоков после запуска Node.js не равно 1. В качестве примера возьмем следующий код.

const http = require('http');

http.createServer((req, res) => {
    res.end('hello');
}).listen(8000, () => {
  console.log('server is listening: ' + 8000);
});

Через Mac Utilities> Activity Monitor вы можете видеть, что количество потоков процесса на самом деле равно 6.

Количество потоков, запущенных Node.js, не равно 1, это из-за пула потоков?

Ответ: Количество потоков не 1, не из-за пула потоков, а из-за V8. После запуска Node.js будет создан экземпляр V8. Экземпляр V8 является многопоточным. Потоки в V8:

  • Основной поток: получить код, скомпилировать и выполнить
  • Поток компилятора: когда выполняется основной поток, код можно оптимизировать.
  • Поток профилировщика: запишите, каким методам требуется время для поддержки оптимизации.
  • Другие потоки: используются для работы по удалению мусора, поскольку потоков несколько, их можно удалять параллельно.

Созданы ли пулы потоков Node.js заранее?

Ответ: Нет, потоки в пуле потоков создаются по требованию.

const http = require('http');
const fs = require('fs');

http.createServer((req, res) => {
  fs.readFile('./c.js', () => {});
  res.end('hello');
}).listen(8000, () => {
  console.log('server is listening: ' + 8000);
});

После запуска приведенного выше кода количество потоков по-прежнему равно 6.

После имитации доступа через ab

ab -n1000 -c20 'http://192.168.76.101:8000/'

Количество потоков стало только 10. Это 10, потому что значение по умолчанию для потоков в пуле потоков равно 4.

Занимает ли асинхронный ввод-вывод пул потоков?

Ответ: Нет, сетевой ввод-вывод не будет занимать пул потоков.

const http = require('http');

http.createServer((req, res) => {
  http.get('http://192.168.1.100');
  res.end('hello');
}).listen(8000, () => {
  console.log('server is listening: ' + 8000);
});

Вышеприведенный код с использованием теста под давлением

ab -n10000 -c20 'http://192.168.76.101:8000'

Ни один поток не создается независимо от того, сколько обращений, количество потоков всегда равно 6.

Файл io обязательно займет пул потоков?

Хотя fs.FSWatcher упоминается в официальной документации, напрямую вызвать его нельзя, есть сопутствующий вопрос по доступу FSWatcher к StackOverflow.stackoverflow.com/questions/3…

Пул резьбы можно использовать только для асинхронного IO?

Ответ: Нет, помимо некоторых операций с интенсивным вводом-выводом, Node.js также поместит его в пул потоков (модуль CRYPTO, ZLIB)

Возможно ли, что DNS-запросы также занимают пул потоков?

Ответ: Да, потому что метод dns.lookup предполагает чтение локальных файлов (например,nsswitch.conf,resolv.confтак же как/etc/hosts). Метод dns.resolve не занимает пул потоков, что является разницей между поиском и разрешением.

Таким образом, следующий код фактически займет пул потоков, потому что http.get по умолчанию использует метод поиска при разборе DNS.

const http = require('http');

http.createServer((req, res) => {
  http.get('http://bj.meituan.com');
  res.end('hello');
}).listen(8000, () => {
  console.log('server is listening: ' + 8000);
});

Пул резьбы используется только внутренне у Node.js Core Modules?

Ответ: Нет, официальная документация имеет следующее описание

You can use the built-in Node Worker Pool by developing a C++ addon. On older versions of Node, build your C++ addon using NAN, and on newer versions use N-API. node-webworker-threads offers a JavaScript-only way to access Node's Worker Pool.

Может ли количество потоков в пуле потоков равняться 0 или оно может быть бесконечным?

Ответ: Оно не может быть равно 0 и не бесконечно. Количество потоков в пуле потоков может быть изменено параметром UV_THREADPOOL_SIZE (по умолчанию – 4). Максимальное количество потоков – 128, а минимальное – 1.

Основной поток никогда не блокируется?

Ответ: Нет, основной поток будет блокироваться при определенных обстоятельствах. Одним из этапов цикла событий Node.js является опрос, который блокируется при определенных обстоятельствах. По этой причине цикл событий выполняется дольше, когда служба на рисунке ниже запускается без каких-либо запросов пользователя, чем когда есть несколько запросов.

Изображение предоставлено: https://medium.com/the-node-js-collection/what-you-should-know-to-really-understand-the-node-js-event-loop-and-its-metrics-c4907b19da4c.

использованная литература

https://nodejs.org/en/docs/guides/dont-block-the-event-loop/ https://medium.freecodecamp.org/what-exactly-is-node-js-ae36e97449f5 https://medium.com/the-node-js-collection/what-you-should-know-to-really-understand-the-node-js-event-loop-and-its-metrics-c4907b19da4c https://jsblog.insiderattack.net/event-loop-and-the-big-picture-nodejs-event-loop-part-1-1cb67a182810