node.js服务器如何优于基于线程的服务器

alt*_*ter 4 javascript node.js

Node.js服务器适用于支持回调函数的基于事件的模型.但我无法理解它比线程等待系统IO的传统线程服务器更好.在基于线程的模型的情况下,当线程需要等待IO时,它被抢占,因此不消耗CPU周期因此不会导致等待时间.

Node.js如何改善等待时间?

sle*_*man 10

当线程需要等待IO时,它会被抢占

实际上,它并没有被抢先一步.抢占是完全不同的东西.会发生什么是线程被阻止.

对于基于事件的模型,会发生类似的事情 基于事件的解释器基本上是状态机.只是,状态机被抽象掉并且对用户不可见.当某事正在等待事件时,它会将控制权传递给解释器.当解释器没有其他任何东西可以处理时,它会阻塞自己等待I/O. 只是,与传统的线程代码不同,解释器等待多个I/O.

在C级别发生的事情是解释器使用的东西如select(),poll(),epoll()和朋友(取决于安装的操作系统和库)来进行阻塞和等待I/O.

现在,为什么基于select()/poll()的机制通常表现更好?实际上,"一般"取决于你的意思.甲的select()基于服务器执行的单个进程/线程的所有代码.最大的性能提升是它避免了上下文切换 - 每次操作系统将控制从一个线程转移到另一个线程时,它必须保存所有相关的寄存器,内存映射,堆栈指针,FPU上下文等,以便其他线程可以从中断处继续执行.这样做的开销可能非常大.

事实上,有一个历史的例子,说明开销有多极端.早在21世纪初,有人开始对Web服务器进行基准测试.令所有人惊讶的是,tclhttpd在提供静态文件方面优于Apache.现在,tcl不仅是一种解释型语言,而且在2000年它是一种非常缓慢的解释语言,因为它没有单独的编译阶段(现在就是这样).Tcl脚本直接以字符串形式解释,使其比C慢大约400 .Apache显然是用C编写的,那么tclhttpd的速度更快?

事实证明,tclhttpd是基于事件的,只在单个线程上运行,而Apache是多线程的.常量线程切换的开销结果证明tclhttpd足以比Apache更好地执行.

当然,总会有妥协.像tclhttpd或node.js 这样的单线程服务器无法利用多个CPU.早在21世纪初,多个CPU就不常见了.这些天他们几乎是默认的.更不用说大多数CPU也是超线程的(超线程为CPU增加硬件以使上下文切换变得便宜).

如今最好的服务器是从历史中学到的,并且是两者的结合.Apache2Nginx使用rarad池:它们是多线程的,但每个线程只提供一个连接.这是两种方法的混合,但管理起来更复杂.

阅读以下文章,以便对此主题进行更深入的讨论:C10K问题


Kae*_*ure 3

线程是相对重量级的对象,其资源占用一直延伸到内核中。当您将线程停放在阻塞系统调用或互斥体或条件变量上时,您会占用所有这些资源,但什么也不做。现在操作系统必须找到更多资源,以便您的程序可以创建另一个线程...然后您也可以闲置它们。没过多久,操作系统就会努力为你的程序收集更多的资源来浪费。

CPU 时间只是全局的一小部分。:-)

  • 实际情况并非如此。当等待 I/O 时(如 OP 中提到的),线程通常会阻塞。从而允许CPU执行其他线程。真正的问题是切换线程的相关成本。基于事件的系统还以“select()/poll()”调用的形式“将资源占用一直延伸到内核”。 (5认同)