为什么Node.js是单线程的?

在基于PHP(或Java/ASP.NET/Ruby)的web服务器中,每个客户端请求都在一个新线程上实例化。但是在Node.js中,所有的客户端都运行在同一个线程上(它们甚至可以共享相同的变量!)我知道I/O操作是基于事件的,所以它们不会阻塞主线程循环。

我不明白的是为什么Node的作者选择它是单线程的?这让事情变得很困难。例如,我不能运行CPU密集型函数,因为它阻塞主线程(新的客户端请求被阻塞),所以我需要生成一个进程(这意味着我需要创建一个单独的JavaScript文件,并在其上执行另一个节点进程)。但是,在PHP中,cpu密集型任务不会阻塞其他客户端,因为每个客户端都在不同的线程上。与多线程web服务器相比,它的优势是什么?

注意:我已经使用集群来解决这个问题,但它并不漂亮。

146307 次浏览

Node.js是作为异步处理的实验显式创建的。理论上,在一个线程上进行异步处理可以在典型的web负载下提供比典型的基于线程的实现更好的性能和可伸缩性。

你知道吗?在我看来,那个理论已经被证实了。一个node.js应用程序不做CPU密集型的事情,可以比Apache或IIS或其他基于线程的服务器多运行数千个并发连接。

单线程、异步的特性确实让事情变得复杂。但是你真的认为它比线程更复杂吗?一个比赛条件可以毁掉你的整个月!或者由于某个地方的某些设置而清空线程池,并看着您的响应时间慢到爬行!更不用说死锁、优先级反转和所有与多线程相关的其他旋转。

最后,我不认为这是普遍的好或坏;这是不同的,有时更好,有时不好。使用正确的工具。

长话短说,节点从V8中抽取,V8内部是单线程的。对于cpu密集型任务,有一些方法可以解决这些限制。

在某一点(0.7),作者试图引入隔离作为实现多线程计算的一种方式,但最终被删除:https://groups.google.com/forum/ !味精/ nodejs zLzuo292hX0 / F7gqfUiKi2sJ

服务器的“每个请求一个线程”模型的问题在于,与事件循环线程模型相比,它们不能很好地适应多种场景。

通常,在I/O密集型场景中,请求花费大部分时间等待I/O完成。在此期间,在“每个请求一个线程”模型中,链接到线程的资源(如内存)是未使用的,内存是限制因素。在事件循环模型中,循环线程选择下一个事件(I/O完成)来处理。因此线程总是处于忙碌状态(当然,如果您正确地编程)。

事件循环模型是所有新事物的闪亮之处,是所有问题的解决方案,但使用哪种模型取决于您需要处理的场景。如果您有一个密集的I/O场景(如代理),则事件库模型将起主导作用,而CPU密集且并发进程数量较少的场景将最适合使用基于线程的模型。

在现实世界中,大多数场景都处于中间位置。你需要平衡可伸缩性的实际需求和开发的复杂性,以找到正确的架构(例如,拥有一个事件基础前端,将CPU密集型任务委托给后端。前端将使用很少的资源等待任务结果。)与任何分布式系统一样,它需要一些努力才能使其工作。

如果你想毫不费力地寻找一颗适用于任何情况的灵丹妙药,那你只会落得脚中弹的下场。