我有这个极小的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
是否为每个传入的连接生成多个工作程序?
最佳答案
JavaScript程序中的线程通过为任务(事件)/作业队列提供服务来工作。从概念上讲,这是一个循环:从队列中拾取一个作业,将该作业运行至完成,拾取下一个作业,将该作业运行至完成。
考虑到这一点,您的带有 promise 的例子是这样的:
var t0 = performance.now();
sleep(1000)
,sleep(1000)
两次。现在有三个Promise,并且三个计时器回调大致安排在同一时间。 Promise.all
。这将保存异步函数的状态并返回一个Promise(无用,因为没有使用init
的返回值)。 sleep
promise 。 then
处理程序),而不是“宏任务”(标准工作)。现代JavaScript引擎在将它们排队的标准作业的末尾处理 promise 作业(即使主队列中已经有另一个标准作业等待完成- promise 作业会跳过主队列)。所以:sleep
promise 将使 promise 工作排队。 Promise.all
的逻辑内对实现处理程序的调用,该逻辑存储实现值并检查是否等待的所有 promise 都已兑现。在这种情况下,它们不是(两个仍然出色),因此没有其他可做的事情,并且 promise 工作已经完成。 sleep
Promise,将一个Promise作业排队以运行其履行处理程序Promise.all
的逻辑调用实现处理程序,该逻辑存储实现值并检查是否所有 promise 都已实现。他们不是,所以它只是返回。 sleep
Promise,并为其实现处理程序排队了Promise作业。 Promise.all
的逻辑运行履行处理程序,该逻辑存储履行结果,查看所有 promise 均已兑现,并将 promise 工作排队以运行其履行处理程序。 init
函数的状态:init
函数执行var t1 = performance.now();
,并显示t1
和t0
之间的差异(大约一秒钟)。 (在该代码中)只涉及一个JavaScript线程。它正在运行一个循环,为队列中的作业提供服务。计时器可能有一个单独的线程,或者主线程可能只是在检查作业之间的计时器列表。 (我必须深入研究Node.js代码才能知道哪个,但是我怀疑后者,因为我怀疑它们正在使用特定于OS的调度功能。)如果是I/O完成而不是计时器,那么我一定要确保它们是由一个单独的非JavaScript线程处理的,该线程会响应来自操作系统的完成并将JavaScript线程的作业排队。
关于javascript - Node.js单线程与并发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57070328/