这一小节是第三章的亮点之一,朴灵作者把Node的异步I/O模型与其他主流并发模型进行横向对比,帮助我们理解Node的定位:它不是万能的,但在大多Web场景下性价比最高。
作者主要对比了以下几种模型:
1. 传统阻塞I/O模型(多线程/多进程,如Apache早期、PHP、Java Servlet)
- 每个连接一个线程 → 线程开销大、上下文切换频繁。
- 优点:编程简单(同步代码)。
- 缺点:并发几千就资源耗尽。
- Node胜出:单线程事件驱动,轻松上万并发。
2. Nginx的事件驱动模型
- 和Node最像:都用事件循环 + 非阻塞I/O(epoll/kqueue)。
- Nginx用C语言实现,多进程 + 事件循环(每个worker一个事件循环)。
- 对比:
- 相似:高并发、低资源。
- 不同:Nginx静态文件/反向代理更极致(零拷贝等优化),Node更灵活(JS动态逻辑)。
- 作者结论:Node适合业务逻辑复杂的服务,Nginx适合纯代理/静态服务。
3. Java的NIO(New I/O)模型
- Java从1.4起支持非阻塞I/O(Selector + Channel)。
- 但Java生态多用线程池(如Tomcat的线程池 + NIO)。
- 对比:Node天生事件驱动,JS单线程无锁;Java多线程编程复杂,容易死锁/竞争。
4. Go语言的Goroutine模型(当时新兴)
- 轻量级用户态线程(goroutine),千千万万不怕。
- 调度器自动在少量OS线程上复用。
- 对比:
- Go并发更细粒度,适合CPU密集 + I/O。
- Node不适合CPU密集(单线程计算阻塞事件循环)。
- 作者预言:Go会是Node的有力竞争者(事实如此,现在很多高性能服务用Go)。
其他提及
- select/poll vs epoll/IOCP:回顾前文,Node通过libuv统一这些底层差异。
作者总结:没有银弹。Node在I/O密集型(如Web API、实时应用)性价比最高;CPU密集用Go/C++;静态服务用Nginx。