在处理大型文件上传时,Node.js会被阻止吗?

nil*_*ing 13 javascript node.js

在处理大型文件上传时,Node.js会被阻止吗?

由于Node.js只有一个线程,所以当进行大文件上传时,所有其他请求都会被阻止吗?

如果是这样,我应该如何处理nodejs中的文件上传?

Amo*_*rni 15

所有的I/O操作都由Node.js处理,内部使用多个线程; 它是I/O功能的编程接口,它是单线程,基于事件和异步的.

因此,您的示例的大上传是由Node.js管理的单独线程执行的,当该线程完成其工作时,您的回调将被放入事件循环队列.

当您执行CPU密集型任务时,它会阻止.假设我们有一个任务compute()需要几乎连续运行,并进行一些CPU密集型计算.


回答主要问题" 我应该如何处理nodejs中的文件上传? "
检查您在服务器上保存文件的代码(或库),它是依赖于writefile()还是 writeFileSync()
如果它正在使用writefile()那么它的异步; 但如果它writeFileSync()是同步版本.


更新:回复评论:

"答案"不,它不会阻塞"是正确的,但解释是完全错误的.JS在一个线程中,I/O在一个(相同的)线程中.事件循环/异步处理/回调使这成为可能.没有多个所需的线程." - by andrey-sidorov

文件操作没有异步API,因此Node.js使用线程池.你可以在libuv的代码中看到它.你可以在lib/fs.js中查看fs.readFile的源代码,你会看到binding.read.每当你在Node的核心模块中看到绑定时,你就会看到一个进入C++领域的门户.使用NODE_SET_METHOD(目标,"读取",读取)可以使用此绑定.如果你知道任何C,你可能会认为这是一个宏 - 它最初是,但它现在是一个函数.

让我们再回到ASYNC_CALLRead,其中一个参数是read:系统调用读.但是等等,这个功能不阻止吗?

是的,但这不是故事的结局.一到libuv介绍表示如下:

" libuv文件系统操作与套接字操作不同.套接字操作使用操作系统提供的非阻塞操作.文件系统操作在内部使用阻塞函数,但在线程池中调用这些函数,并在应用程序时通知使用事件循环注册的观察者需要互动. "

简介: Node API方法writeFile()是异步的,但这并不一定意味着它在下面是非阻塞的.正如libuv 书所指出的,套接字(网络)代码是非阻塞的,但文件系统更复杂.有些东西是基于事件的(kqueue),有些则使用线程池(如本例所示).

考虑更多信息,请考虑浏览开发Node.js的C代码:

  • 答案"不,它不会阻止"是正确的,但解释是完全错误的.JS在一个线程中,I/O在一个(相同的)线程中.事件循环/异步处理/回调使这成为可能.无需多线程. (3认同)
  • @Andrey Sidorov 感谢您的评论,这让我的解释超出了要求.. :) (2认同)