【发布时间】:2014-04-10 21:02:30
【问题描述】:
Node.js 在处理大文件上传时会被阻塞吗?
由于 Node.js 只有一个线程,是不是在上传大文件时所有其他请求都会被阻塞?
如果是这样,我应该如何处理 nodejs 中的文件上传?
【问题讨论】:
标签: javascript node.js
Node.js 在处理大文件上传时会被阻塞吗?
由于 Node.js 只有一个线程,是不是在上传大文件时所有其他请求都会被阻塞?
如果是这样,我应该如何处理 nodejs 中的文件上传?
【问题讨论】:
标签: javascript node.js
所有 I/O 操作都由 Node.js 处理,内部使用多个线程;它是单线程、基于事件和异步的 I/O 功能的编程接口。
因此,您的示例的大上传是由 Node.js 管理的单独线程执行的,当该线程完成其工作时,您的回调将被放入事件循环队列中。
当您执行 CPU 密集型任务时,它会阻塞。假设我们有一个任务 compute() 需要几乎连续运行,并进行一些 CPU 密集型计算。
writefile()或writeFileSync()?writefile(),那么它是异步的;但如果是writeFileSync(),它是同步版本。
“答案“不,它不会阻塞”是正确的,但解释是 完全错误。 JS 在一个线程中,I/O 在一个线程中(相同) 线。事件循环/异步处理/回调使这成为可能。不需要多个线程。 " - andrey-sidorov
没有用于文件操作的异步 API,因此 Node.js 使用线程池。你可以在libuv的代码中看到。你可以在lib/fs.js 中查看 fs.readFile 的源代码,你会看到 binding.read。每当您在 Node 的核心模块中看到绑定时,您就是在寻找进入 C++ 领域的门户。使用 NODE_SET_METHOD(target, "read", Read) 可以使用此绑定。如果你知道任何 C 语言,你可能会认为这是一个宏——它最初是,但现在它是一个函数。
回到Read 中的ASYNC_CALL,其中一个参数是read:系统调用读取。但是等等,这个功能不会阻塞吗?
是的,但这不是故事的结局。 Introduction to libuv 表示以下内容:
"libuv文件系统操作不同于socket操作。socket操作使用操作系统提供的非阻塞操作。文件系统操作在内部使用阻塞函数,但是在线程池中调用这些函数并且当需要应用交互时通知注册到事件循环的观察者。"
总结:
Node API 方法writeFile() 是异步的,但这并不一定意味着它在下面是非阻塞的。正如 libuv book 指出的那样,套接字(网络)代码是非阻塞的,但文件系统更复杂。有些事情是基于事件的(kqueue),有些事情使用线程池(如本例)。
考虑通过C code on which Node.js is developed了解更多信息:
【讨论】:
这取决于用于完成该任务的功能。如果您使用的是异步函数,那么 Node.js 将不会阻塞。但也有同步函数,例如fs.readFileSync (FileSystem Doc),会阻塞执行。
请注意并选择异步函数。这样 Node.js 将在外部库完成慢速任务/等待时继续运行。一旦这些任务完成,事件循环将处理结果并执行您的回调。
您可以在此处阅读有关事件循环的更多信息:Understanding the Node.js event loop
【讨论】:
这就是 node.js 异步的确切原因。
node.js 中的大多数(全部?)函数涉及输入/输出操作(瓶颈是 CPU 或 RAM 以外的其他设备)操作发生在单独的线程上,让您的 node.js 服务器在等待时执行一些其他代码.
【讨论】: