在高并发场景下,很多 Node.js 服务开发者都会遇到内存暴涨、慢请求阻塞、甚至服务崩溃的问题。本篇文章将从 Node 原生 HTTP 模块的高并发处理机制、隐藏的内存炸弹 到 生产级架构为什么要加 Nginx,帮你全面梳理 Node 高并发的性能挑战和解决方案。
一、Node HTTP 模块的高并发机制
Node.js 的并发模型基于 事件循环(Event Loop)+ 非阻塞 I/O,依赖底层的 libuv 和操作系统的 epoll/kqueue/IOCP:
- 单线程事件循环,避免线程开销。
- 请求在事件循环中被调度,不会为每个请求创建独立线程。
- 内置 Stream + Backpressure 机制,用于控制数据流,防止 Writable/Readable buffer 无限增长。
关键点
-
Stream 与背压(Backpressure)
req是 Readable Stream,res是 Writable Stream。- 当写入速度快于客户端读取速度时,
res.write()会返回false,必须等待drain事件再继续写入,否则 buffer 会堆积。
-
Socket buffer & highWaterMark
- Node 的默认 buffer 大小有限(highWaterMark ≈ 16KB)。
- 超过 buffer 会触发 pause/resume 机制,防止内存无限增长。
-
连接与超时控制
server.keepAliveTimeout、server.headersTimeout、server.requestTimeout可防止慢连接占用资源。- OS 级 backlog 控制,超过队列长度的连接会被拒绝。
-
GC 自动回收
- 请求完成后,V8 会回收
req、res、buffer 等对象。 - 内存泄漏通常来自业务代码持有全局引用或闭包未释放。
- 请求完成后,V8 会回收
二、隐藏的内存炸弹
1. Slowloris(慢请求攻击)
Slowloris 攻击通过极慢发送 HTTP Header,占用 Node 连接资源:
GET / HTTP/1.1
Host: example.com
X-a: 1
(停 10 秒)
X-b: 2
特点:
- 请求未完成,
request事件不会触发。 - 连接被占用,socket buffer 堆积。
- 攻击大量慢连接时,Node 内存和文件描述符会迅速耗尽。
防御策略:
server.headersTimeout = 5000; // header 超时断开
server.requestTimeout = 10000; // 请求超时
server.keepAliveTimeout = 3000; // 长连接释放
server.maxHeadersCount = 100; // 限制 header 数量
2. 慢响应客户端(Slow Response Client)
这是比 Slowloris 更隐蔽的性能问题:
- 客户端接收数据极慢(例如 10 KB/s)。
- Node
res.write()的 buffer 会持续堆积。 - 高并发慢客户端会导致内存暴涨,甚至服务崩溃。
示例:
const file = fs.createReadStream("10GB.zip");
file.pipe(res); // 正确方式,自动处理背压
错误写法:
while(data) {
res.write(chunk); // 忽略 backpressure
}
解决方案:
- 使用
stream.pipe(res)自动处理背压。 - 检查
res.write()返回值并监听drain。 - 限制响应大小或分页返回。
- 在生产环境前加 Nginx 进行缓冲和速率控制。
三、为什么大厂 Node 服务前面一定要加 Nginx
大厂架构中 Node 服务几乎总是被 Nginx 包裹,原因总结如下:
1. 处理慢客户端和慢请求攻击
Nginx 可以:
- 缓存响应,保护 Node 内存。
- 控制发送速率,断开慢客户端。
- 防止 Slowloris 攻击。
2. 静态资源高性能服务
- Node 处理静态文件会经过 JS 层和 V8 引擎,CPU 和 GC 成本高。
- Nginx 使用
sendfile、zero-copy,几乎零 CPU 消耗,适合图片、JS、CSS、视频等。
3. 高并发连接管理
- Nginx 可以轻松处理十万级以上 TCP 连接。
- 连接复用、限流、空闲管理比 Node 内置机制更成熟。
4. 安全防护
- 限速 (
limit_req)、限连接 (limit_conn)。 - 限制请求体大小 (
client_max_body_size)。 - 防 Slowloris(header timeout)。
5. 负载均衡与集群管理
- 将流量分发给 Node Cluster。
- 健康检查、权重调度、故障转移。
6. TLS/HTTPS 终止
- HTTPS 加解密 CPU 密集。
- Nginx 终止 TLS 后再转发 HTTP 给 Node,减轻 Node 负担。
7. 缓存和灰度发布
- 缓存热点 API 请求,减轻 Node 压力。
- 蓝绿/灰度部署和流量切分,升级更安全。
四、Node + Nginx 的生产级架构示意
Internet
↓
CDN
↓
WAF
↓
Nginx / Gateway
↓
Node Cluster (多进程)
↓
Service
↓
Database
- Node 专注业务逻辑。
- Nginx 负责网络、缓存、安全、负载均衡。
- 每层职责分明,系统稳定、高效、易扩展。
五、总结
Node.js 在高并发下虽然有 事件循环 + 非阻塞 I/O + Stream 背压 机制,但仍然容易被:
- 慢请求(Slowloris)
- 慢响应客户端(Slow Response Client)
- 超大响应和错误业务逻辑
拖垮内存和 CPU。
大厂解决方案:
- 充分利用 Node 内置的 timeout、backpressure、stream。
- 在 Node 前增加 Nginx 做网络层缓冲、速率控制、TLS 终止和负载均衡。
- 静态资源交给 Nginx。
- 分层架构 + CDN + WAF 形成完整防护体系。
核心理念:Node 专注业务逻辑,网络与安全交给 Nginx,才能实现高并发下稳定、高效的生产级服务。
💡 小贴士:
- 使用
stream.pipe()避免内存积压。 - 对慢客户端进行限流或断开。
- Node HTTP 服务千万不要直接暴露公网。
- Nginx + Node 的组合不仅提升性能,还提高了安全性和运维便利性。