Node.js内部是否使用线程/线程池?

5

我决定熟悉node.js,并阅读了一些相关文章。有一个问题一直不太清楚,那就是当调用node.js函数时,它是否会创建新的线程和/或在线程池中调度任务。

例如,如果我调用fs.readFile,它会在不同的线程上执行吗?

如果是,[如何]可以编写自己的函数readFileCustomizeddoLongOperation以在不同的线程上运行?


@jfriend00 没看过这个,但肯定很有用。感谢您的建议。 - Andrew Savinykh
刚试图找到与 fs.readFile 相关的所有源代码:fs.readFile > fs.read > ASYNC_CALL(read(2)) (macro) > FSReqWrap > ReqWrap > BaseObject。如果您想要检查 fs.readFile 的内在特性,这可能需要一些时间。 - Zeta
1个回答

9

对于文件操作,Node.js没有异步API,因此使用线程池来处理。你可以在libuv的代码中看到它。

该线程池最多可以运行4个线程

static uv_thread_t default_threads[4];

使用uv__work_submit发布阻塞FS任务。例如,这是read的实现方式

int uv_fs_read(uv_loop_t* loop, uv_fs_t* req,
               uv_file file,
               void* buf,
               size_t len,
               int64_t off,
               uv_fs_cb cb) {
  INIT(READ);
  req->file = file;
  req->buf = buf;
  req->len = len;
  req->off = off;
  POST;
}

...

#define POST                                                                  \
  do {                                                                        \
    if ((cb) != NULL) {                                                       \
      uv__work_submit((loop), &(req)->work_req, uv__fs_work, uv__fs_done);    \
      return 0;                                                               \
    }                                                                         \
    else {                                                                    \
      uv__fs_work(&(req)->work_req);                                          \
      uv__fs_done(&(req)->work_req, 0);                                       \
      return (req)->result;                                                   \
    }                                                                         \
  }                                                                           \
  while (0)

如果您想要实现自己的线程,可以查看这个优秀的介绍


我认为在IO期间没有任何线程被阻塞。 - usr
1
libuv 最终使用了 stdio 的 read:https://github.com/joyent/libuv/blob/v0.10.19/src/unix/fs.c#L184,这是阻塞的。 - Laurent Perrin
谢谢你,我已经学习了最后链接的文章,但它与libuv有关,我想知道其中有多少在node.js中是可见的。看起来线程池/线程并没有完全暴露。 - Andrew Savinykh
我不太有资格阅读C代码。我想知道这段代码路径是否被调用过。这将非常违背libuv的目的,至少可以说是令人惊讶的。您是否愿意看一下套接字IO的实现方式? - usr
1
所有网络IO都是完全异步的(例如,它使用Linux的epoll)。然而,文件系统始终在线程池中阻塞。 - Laurent Perrin
显示剩余2条评论

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