我有这个极小的Node.js服务器:
http.createServer(function (req, res) {
var path = url.parse(req.url).pathname;
if (path === "/") {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.write('Hello World');
res.end('\n');
} else {
if (!handler.handle(path, req, res)) {
res.writeHead(404);
res.write("404");
res.end();
}
}
}).listen(port);
做完一些基准测试后,我发现在高并发性(> 10000个并发连接)下性能会大大下降。我开始更深入地研究Node.js并发性,搜索越多,我就越困惑...
我从http范例中创建了一个最小的示例,以尝试更好地理解事物:
function sleep(duration) {
return new Promise(resolve => setTimeout(resolve, duration));
}
var t0 = performance.now();
async function init() {
await Promise.all([sleep(1000), sleep(1000), sleep(1000)]);
var t1 = performance.now();
console.log("Execution took " + (t1 - t0) + " milliseconds.")
}
init()
// Execution took 1000.299999985145 milliseconds.
据我了解,JavaScript在单个线程上运行。话虽这么说,但我不能像这样:
| 1 second |
Thread #One >>>>>>>>>>>>>>
Thread #One >>>>>>>>>>>>>>
Thread #One >>>>>>>>>>>>>>
...显然这没有意义。
这是thread
与worker
相对的术语问题吗?
| 1 second |
Thread #One (spawns 3 workers)
Worker #One >>>>>>>>>>>>>>
Worker #Two >>>>>>>>>>>>>>
Worker #Three >>>>>>>>>>>>>>
???
Node.js如何是单线程的,但能够并行处理三个函数?如果我对并行工作程序正确,http
是否为每个传入的连接生成多个工作程序?
答案 0 :(得分:1)
JavaScript程序中的线程通过为任务(事件)/作业队列提供服务来工作。从概念上讲,这是一个循环:从队列中拾取一个作业,将该作业运行至完成,拾取下一个作业,将该作业运行至完成。
请记住,您的诺言示例如下:
var t0 = performance.now();
sleep(1000)
,其中
sleep(1000)
。现在有三个Promise,并且三个计时器回调大致安排在同一时间。Promise.all
兑现这些承诺。这样可以保存异步函数的状态并返回一个Promise(无用,因为没有使用init
的返回值)。sleep
承诺。then
处理程序),而不是“宏任务”(标准任务)。现代JavaScript引擎会在将它们排队的标准作业的末尾处理承诺作业(即使主队列中已经有另一个标准作业等待完成-承诺作业会跳过主队列)。所以:
sleep
承诺将使承诺工作排队。Promise.all
的逻辑内触发对实现处理程序的调用,该逻辑存储实现值并检查是否已等待其等待的所有诺言。在这种情况下,它们不是(两个仍然出色),因此无可奉告,诺言工作也就完成了。sleep
承诺,对一个保证工作进行排队以运行其履行处理程序Promise.all
的逻辑调用实现处理程序,该逻辑存储实现值并检查是否所有承诺都已实现。它们不是,所以它只是返回。sleep
承诺,并为其履行处理程序排队了一个承诺工作。Promise.all
的逻辑运行实现处理程序,该处理程序存储实现结果,看到所有承诺都已兑现,然后将承诺工作排队以运行 履行处理程序。init
函数的状态:
init
函数执行var t1 = performance.now();
,并显示t1
和t0
之间的差异,大约是一秒钟。(该代码中)只涉及一个JavaScript线程。它正在运行一个循环,为队列中的作业提供服务。计时器可能有单独的线程,或者主线程可能只是在检查作业之间的计时器列表。 (我必须深入研究Node.js代码才能知道哪个,但我怀疑后者,因为我怀疑它们使用的是操作系统特定的调度功能。)如果是I / O完成而不是计时器,那我相当确定这些是由单独的非JavaScript线程处理的,该线程会响应来自操作系统的完成并将JavaScript线程的作业排队。