Nginx 连接复用与四层负载均衡
对比四层(stream)与七层(http)转发,从操作系统并发与 I/O 机制出发系统性说明:Nginx 的网络设计、连接复用原理与 Linux 内核调优,并附可执行配置与观测建议。
1. 从操作系统角度看网络并发模型
高并发网络服务的核心是“如何在有限 CPU/内存下同时处理大量连接”。关键是并发模型与 I/O 机制:
- 进程/线程模型:每连接一个进程/线程,易编程,但上下文切换与栈内存开销在 1k~10k 连接下迅速放大。
- 事件驱动模型(Reactor/Proactor):少量线程管理海量非阻塞 fd,依赖内核事件通知。
内核 I/O 通知机制:
- select/poll:线性扫描,fd 数/开销受限,不适合高并发。
- epoll(Linux):O(1) 监听大量 fd,边缘/水平触发,
EPOLLEXCLUSIVE降低惊群。 - kqueue(BSD/macOS):高效通用事件队列。
- IO_uring(Linux 新):提交/完成队列,绕过部分系统调用开销;Nginx 主线仍以 epoll 为主。
Reactor vs Proactor:Nginx 采用 Reactor(事件到来再发起 read/write),Windows 下的 IOCP 更接近 Proactor。
常见瓶颈点:
- fd 限制(
ulimit -n、worker_rlimit_nofile、fs.file-max)。 - 监听/握手队列(
somaxconn、tcp_max_syn_backlog、SYN flood)。 - 收发队列与网卡(
netdev_max_backlog、RPS/RFS/XPS、队列/中断亲和)。 - 拥塞控制与队列管理(BBR、
fq、TFO)。
2. Nginx 的网络设计模型
Nginx 采用 master + 多 worker 的事件驱动架构:
- master:管理配置、热重载、worker 生命周期。
- worker:每个 worker 一个事件循环,使用
epoll/kqueue管理大量非阻塞连接;worker_processes auto;通常与 CPU 核数一致。 - 连接与请求分离:一个连接可承载多个请求(HTTP/1.1 keepalive、HTTP/2 多路复用)。
- accept 协调:
accept_mutex避免惊群;或reuseport让每个 worker 拥有独立监听套接字。 - 零拷贝与发送优化:
sendfile、tcp_nopush、tcp_nodelay、aio threads。
事件与监听示例:
worker_processes auto;
worker_rlimit_nofile 1048576;
events {
use epoll; # Linux 下优先 epoll;macOS/FreeBSD 为 kqueue
worker_connections 65535;
multi_accept on;
# accept_mutex on; # 与 reuseport 二选一
}
server {
listen 80 reuseport backlog=65535;
# listen 443 ssl http2 reuseport fastopen=512;
}
3. 连接复用:客户端、Nginx 与上游
目标:减少握手与 TLS 开销、降低 TIME_WAIT 与端口消耗、提升吞吐。
- 客户端->Nginx:
- HTTP/1.1 keepalive 串行复用
- HTTP/2 多路复用并发流
- HTTP/3(QUIC)在 UDP 上实现多路复用与 0-RTT
- Nginx->上游:
upstream keepalive将代理到上游的连接复用,显著降低后端握手压力- 连接池为“每 worker 独立”,容量需乘以 worker 数
HTTP/1.1 与上游 keepalive:
http {
upstream api_backend {
server 10.0.0.2:8080 max_fails=2 fail_timeout=10s;
keepalive 256; # 每 worker 空闲长连接上限
}
server {
listen 80 reuseport backlog=65535;
keepalive_requests 10000;
keepalive_timeout 75s;
location / {
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_connect_timeout 5s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
proxy_pass http://api_backend;
}
}
}
四层(stream)与上游:
stream {
upstream mysql_backend {
server 10.0.0.1:3306 max_fails=2 fail_timeout=10s;
}
server {
listen 3306 reuseport backlog=32768;
proxy_connect_timeout 3s;
proxy_timeout 30s;
proxy_pass mysql_backend;
}
}
取舍提示:
- 上游存在会话亲和或连接态时,需配合一致性哈希/粘性策略,避免跨请求状态泄漏。
- 短连接/突发场景不宜给过大 keepalive 池,避免端口/内存占用。
- 数据库协议建议交由专业代理(ProxySQL、pgbouncer)做更精细的连接池与语句复用。
stream { upstream mysql_backend { server 10.0.0.1:3306 max_fails=2 fail_timeout=10s; } server { listen 3306; proxy_pass mysql_backend; } }
4. Linux 内核网络优化
推荐基线(按环境渐进验证):
# /etc/sysctl.d/99-nginx-tuning.conf
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 250000
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syncookies = 1
net.ipv4.ip_local_port_range = 10000 65000
fs.file-max = 2097152
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 5
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.ipv4.tcp_rmem = 4096 87380 134217728
net.ipv4.tcp_wmem = 4096 65536 134217728
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
net.ipv4.tcp_fastopen = 3
Nginx 侧连接与 fd:
worker_rlimit_nofile 1048576;
events { worker_connections 65535; }
注意事项:
tcp_tw_recycle已移除,勿用;tcp_tw_reuse收益有限,勿过度依赖。- 过度缩短
tcp_fin_timeout可致异常断流;以观测为准。 reuseport与accept_mutex二选一;多核下普遍优先reuseport。- 网卡队列/中断亲和等需要硬件与驱动配合,谨慎变更。
5. 观测与压测
- Nginx:
stub_status、$upstream_response_time分位数、active/reading/writing 分布。 - 系统:
ss -s、ss -ti、sar -n TCP,DEV、ethtool -S、/proc/net/netstat。 - 压测:
wrk(HTTP/1.x)、h2load(HTTP/2/3)、iperf3(链路)。
示例:
wrk -t8 -c1024 -d60s --latency http://127.0.0.1/
h2load -n 100000 -c 200 -m 100 https://127.0.0.1:443/
6. 常用配置快照
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 75s;
keepalive_requests 10000;
upstream api_backend { server 10.0.0.2:8080; keepalive 256; }
server {
listen 80 reuseport backlog=65535;
location / {
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_pass http://api_backend;
}
}
}
7. 排错 Checklist
- 5xx 或 upstream timed out:核查后端与上游连接池、
proxy_*_timeout、网络丢包。 - 连接拒绝或超时:检查
somaxconn/backlog、worker_connections、ss -lnt中队列与监听状态。 - TIME_WAIT/端口耗尽:扩大
ip_local_port_range与上游 keepalive,排查异常关闭。 - 吞吐增长受限:核查
sendfile、tcp_nopush、NIC 队列、CPU 亲和与磁盘 I/O。