处理大型文件上传时Node.js会被阻止吗?
由于Node.js只有一个线程,所以在执行大文件上传时,所有其他请求都会被阻止吗?
如果是这样,我应该如何处理nodejs中的文件上传?
答案 0 :(得分:14)
所有I / O操作都由Node.js处理,内部使用多个线程;它是I / O功能的编程接口,是单线程,基于事件和异步的。
因此,您的示例的大上传是由Node.js管理的单独线程执行的,当该线程完成其工作时,您的回调将被放到事件循环队列中。
当你执行CPU密集型任务时,它会阻止。让我们说我们有一个任务compute(),它需要几乎连续运行,并进行一些CPU密集型计算。
<小时/> 回答主要问题&#34; 我应该如何处理nodejs中的文件上传?&#34;writefile()
还是writeFileSync()
?如果它正在使用writefile()
那么它是异步的;但如果它是writeFileSync()
,则它是同步版本。
<小时/> 更新:回复评论:
&#34;答案&#34;不,它不会阻止&#34;是正确的,但解释是 完全错了。 JS在一个线程中,I / O在一个(相同) 线。事件循环/异步处理/回调使这成为可能。无需多线程。 &#34; - andrey-sidorov
文件操作没有异步API,因此Node.js使用线程池。您可以在libuv的代码中看到它。您可以在lib/fs.js中查看fs.readFile的源代码,您将看到binding.read。每当你在Node的核心模块中看到绑定时,你就会看到一个进入C ++领域的门户。使用NODE_SET_METHOD(目标,&#34;读取&#34;,读取)可以使用此绑定。如果您知道任何C,您可能会认为这是一个宏 - 它最初是,但它现在是一个函数。
回到ASYNC_CALL
中的Read
,其中一个参数是read
:系统调用。但等等,这个功能阻止了吗?
是,但这不是故事的结尾。 Introduction to libuv表示以下内容:
&#34; libuv文件系统操作与套接字操作不同。套接字操作使用操作系统提供的非阻塞操作。文件系统操作在内部使用阻塞函数,但在线程池中调用这些函数,并在需要应用程序交互时通知在事件循环中注册的观察者。 &#34;
<强>要点:强>
节点API方法writeFile()
是异步的,但这并不一定意味着它在下面是非阻塞的。正如libuv book指出的那样,套接字(网络)代码是非阻塞的,但文件系统更复杂。有些东西是基于事件的(kqueue),有些则使用线程池(如本例所示)。
考虑更多信息,请考虑浏览C code on which Node.js is developed:
答案 1 :(得分:2)
这取决于用于完成该任务的功能。如果您使用的是异步函数,那么Node.js将不会阻塞。但也有同步函数,例如fs.readFileSync
(FileSystem Doc),它们将阻止执行。
注意并选择异步功能。这样Node.js将继续运行,而外部库完成缓慢的任务/等待。完成这些任务后,Event Loop将处理结果并执行回调。
您可以在此处详细了解“事件循环”:Understanding the Node.js event loop
答案 2 :(得分:1)
这就是node.js异步的确切原因。
node.js中涉及输入/输出操作的大多数(全部?)函数(其中瓶颈是除CPU或RAM之外的其他设备)操作发生在一个sepparate线程上,让你的node.js服务器在等待时做一些其他代码