问题描述
当 Node 的事件循环完全耗尽时,进程就存在了.然而,这不会发生在例如 HTTP 服务器上,因为 server.listen()
.但是这个函数到底做了什么?
When Node's event loop is fully drained, the process exists. However this doesn't happen on an HTTP server for example, because of server.listen()
. But what does that function do exactly?
查看代码和,它最终调用了 self._listen2()
在 process.nextTick
上发出listening"事件,并从 DefaultTriggerAsyncId()
获取异步钩子 ID.
Looking at the code and an old incomplete answer, it eventually calls self._listen2()
which emits a "listening" event on process.nextTick
, and gets an async hook ID fromDefaultTriggerAsyncId()
.
但是,我还是不明白.我在这里缺少什么?仅此代码如何导致事件循环保持空闲"?函数是如何包裹在C端的?实际执行此操作的代码行在哪里?
However, I still don't get it. What am I missing here? How does only this code cause the event loop to keep 'idling'? How is the function wrapped on the C side? Where's the line of code that actually does that?
谢谢!
推荐答案
真正的答案终于出自伯特贝尔德,他在 libuv 上工作.
The real answer finally came from Bert Belder, who worked on libuv.
每当 Node 将一个将在未来某个时间点解决的操作排队时,想想异步函数或计时器,它都有一个 ref——一个标记,提醒自己它正在等待一些未来的工作.事件循环检查是否有任何引用.如果 ref 计数器为 0 ,则 Node 退出进程.如果有 refs,事件循环会回到开始并做它的事情.你可以把它想象成一个超级简单的 while(refCounter)
循环.
Every time Node queues an action that will resolve at some point in the future, think async functions or timers, it has a ref – a mark to remind itself it’s waiting on some future work. The event loop checks if there are any refs. If the ref counter is 0 , Node exits the process. If there are refs, the event loop goes back to the start and does its thing. You can think of it as a super simple while(refCounter)
loop.
那么,服务器会发生什么?这个确切的过程,除了 listen 函数不会递减 ref 计数器.事件循环看到总是至少有一个引用,所以它永远不会结束这个过程,而是回到开始并循环直到有新的事情发生.
So, what happens with a server? This exact process, except the listen function doesn’t decrement the ref counter. The event loop sees there’s always at least one ref left, so it never ends the process instead goes back to the start and loops until something new happens.
您可以通过在带有 net 或 http 模块的服务器对象上使用 server.unref()
来查看这一点.unref 方法也可用于其他对象,它告诉 Node 在事件循环结束时计数时忽略该特定函数的 ref.如果你运行下面的代码,你会看到 Node 关闭进程,即使它开始监听端口.
You can see this by using server.unref()
on the server object with the net or http modules. The unref method, available on other objects as well, tells Node to ignore the ref for that specific function when counting at the end of the event loop. If you run the code below you’ll see Node closes the process, even though it starts listening to the port.
const http = require("http");
http
.createServer((req, res) => {
res.writeHead(200);
res.end("Bye bye");
})
.listen(3333)
.unref();
这篇关于Node 如何使服务器进程保持活动状态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!