Node JS,createServer和事件循环

12

在Node的幕后,http模块的createServer方法(及其回调)如何与事件循环交互?我是否可以在用户空间中构建类似于createServer的功能,还是需要更改Node的底层系统代码?

也就是说,我对Node事件循环的一般理解是:

  1. 事件循环开始
  2. Node查找任何要运行的回调函数
  3. Node运行这些回调函数
  4. 事件循环再次开始,重复进行

我仍然有点不明白的是createServer如何适配到事件循环中。如果我像下面这样做

var http = require('http');

// create an http server  and handle with a simple hello world message
var server = http.createServer(function (request, response) {
    //...
});

我告诉Node当有HTTP请求时运行我的回调函数。这似乎与我了解的事件循环模型不兼容。似乎有一些非用户空间和非事件循环正在侦听HTTP请求,然后在收到请求时运行我的回调函数。

换句话说——如果我考虑实现自己的createServer版本,我无法想到一种方法来做到这一点,因为我安排的任何回调都只会运行一次。 createServer是否仅使用setTimeoutsetInterval来不断重新检查传入的HTTP请求?还是有更底层、更高效的东西正在进行?我知道我不需要完全理解这个过程才能编写高效的Node代码,但我很好奇底层系统是如何实现的。

(我尝试跟着Node源码走,但由于不熟悉Node模块系统或系统代码中深层次的编码模式的传统假设,速度很慢)


Node拥有较低级别的网络支持http://nodejs.org/api/net.html,因此如果您需要的是这样的话,您应该能够创建自己的HTTP实现。Node的事件系统是通过实现*EventEmitter*将其构建到您的类中的。http://nodejs.org/api/events.html - user2437417
最终,如果你的问题是关于底层系统如何实现的,那么我不知道比阅读源代码更好的方法了。 - user2437417
这非常正确,@CrazyTrain。但是要真正深入了解一个代码案例可能需要几周甚至几个月的时间。有时候让别人指点一下方向可以节省大量时间。 - Alana Storm
2个回答

3

http.createServer 是一个方便的方法,用于创建一个新的 http.Server() 并将回调函数作为事件监听器附加到 request 事件上。当然,Node.js 的 http 库也实现了协议解析。

没有对事件循环进行持续轮询,Node.js 等待 C++ tcp 绑定在套接字上接收数据,然后将该数据作为 buffer 传递给您的回调函数。

如果您要实现自己的 http 解析器,可以将 net.Server 对象作为基础。请参见 Node.js 的实现:https://github.com/joyent/node/blob/master/lib/_http_server.js#L253


3
谢谢Ben提供的信息。我想我的实际问题是:“节点在哪里/如何等待C++ tcp绑定在套接字上接收数据?”。这与(似乎是全局和未定义的)listen函数的调用有关,它位于https://github.com/joyent/node/blob/master/lib/net.js#l294吗?还是这个问题太长了,在评论中无法解释清楚? - Alana Storm
它等待在libuv库中。如果您正在使用Linux,则代码在此处:https://github.com/joyent/libuv/blob/master/src/unix/linux-core.c#L75 - Andrey Sidorov
这可能是了解 epoll 系统调用的好开始:http://en.wikipedia.org/wiki/Epoll - Andrey Sidorov
1
@AndreySidorov 这是有用的信息,但不完全是我要找的。我想知道C程序员或JavaScript程序员说“当这个网络事件发生时,将数据发送到这个JavaScript代码位”的那一点。 - Alana Storm

1

Events库负责生成和处理事件,正如CrazyTrain在评论中提到的那样。它有一个EventEmitter类,用于服务器、套接字和流等。

像你说的那样,事件循环是一个无限循环,在每个tick后执行回调函数。提供给http服务器的回调函数是一个事件处理程序,特别是针对request事件。

var server = http.createServer(function (request, response) //request handler

事件处理程序可以被多次执行。 http.serverEventEmitter 的一个实例。它的工作方式是首先解析传入的请求。解析后,它发出 请求 事件。然后事件发射器使用提供的参数执行请求的回调函数。

您说得对,EventEmitter 不是事件循环的一部分。它需要由模块或库的开发人员实现,只能使用模块的用户提供的处理程序。但最重要的是,它提供了必要的机制来实现事件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接