theme: default themeName: "默认主题" title: "Nginx并发从2000到20000,我只改了这6个配置"
Nginx并发从2000到20000,我只改了这6个配置
有个做电商的朋友找我,说大促时Nginx扛不住,并发一上2000就开始502,问我怎么优化。我远程上去看了一下他的Nginx配置,好家伙,基本全是默认值。
花了半小时调了6个配置,压测并发直接拉到20000,响应时间还降了一半。今天把这6个配置和背后的原理写出来,对你一定有用。
配置一:worker_processes 和 worker_cpu_affinity
默认配置:
worker_processes 1;
这是最基础的——1个worker进程处理所有连接。多核CPU根本没利用上。
优化后:
# 自动匹配CPU核心数
worker_processes auto;
绑定worker到CPU核心,减少上下文切换
worker_cpu_affinity auto;
原理: Nginx是单线程事件驱动模型,一个worker只能跑在一个CPU核心上。`auto`会自动创建和CPU核心数相同的worker进程,`worker_cpu_affinity auto`让每个worker绑定到固定核心,避免CPU缓存失效。
实测8核服务器,1个worker → 8个worker,吞吐量提升约6倍(不是8倍,因为有锁竞争和上下文切换开销)。
配置二:worker_connections
默认配置:
events {
worker_connections 1024; }
一个worker最多1024个连接?对于现代服务器来说太保守了。
优化后:
events {
worker_connections 65535; use epoll; # Linux必开 multi_accept on; # 一次接受所有新连接 }
算一下最大并发: `worker_processes × worker_connections = 8 × 65535 = 524280`,但实际能达到的并发还受系统文件描述符限制,所以还需要改系统参数:
# 修改文件描述符限制
echo "* soft nofile 65535" >> /etc/security/limits.conf echo "* hard nofile 65535" >> /etc/security/limits.conf
临时生效
ulimit -n 65535
同时在Nginx配置里也要设置:
worker_rlimit_nofile 65535;
配置三:keepalive_timeout 和 keepalive_requests
默认配置:
keepalive_timeout 75s;
keepalive_requests 默认1000
这个默认值有两个问题:75秒太长了,浪费连接资源;1000次请求太少,高并发下连接会频繁重建。
优化后:
keepalive_timeout 30s;
keepalive_requests 10000;
原理: 长连接保持太久会占着worker的连接槽不放,新连接进不来。30秒是个比较平衡的值——足够覆盖用户浏览一个页面的时间,又不会浪费太多资源。
`keepalive_requests`从1000提到10000,避免高频访问时连接被强制断开重建。
还有一个经常被忽略的配置——与上游服务器的长连接:
upstream backend {
server 127.0.0.1:8080; keepalive 32; # 与上游保持32个长连接 }
server { location / { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Connection ""; } }
这可能是最被低估的优化。 没有这个配置时,Nginx每次转发请求都要跟后端建一个新TCP连接,三次握手+慢启动,延迟至少多3-5ms。有了长连接池,请求直接复用已有连接,延迟大幅降低。
配置四:sendfile 和 tcp_nopush
默认这两个都是关闭的。
优化后:
sendfile on;
tcp_nopush on; tcp_nodelay on;
原理:
- `sendfile on`:让操作系统内核直接把文件内容从磁盘读到内核缓冲区再发到网卡,跳过用户态拷贝。对静态文件服务性能提升巨大。
- `tcp_nopush on`:在发送响应头时,把响应头和第一个数据包一起发出去,减少网络包数量。和`sendfile`配合使用效果最好。
- `tcp_nodelay on`:禁用Nagle算法,小包立即发送,降低延迟。和`tcp_nopush`看似矛盾,实际上Nginx会在合适的时机切换——发送大块数据时用`tcp_nopush`攒包,最后一个小包用`tcp_nodelay`立即发出。
三者配合,静态文件服务的吞吐量能提升30%-50%。
配置五:gzip压缩
默认gzip是关闭的。对于文本类响应(HTML/CSS/JS/JSON),开启gzip可以减少60%-80%的传输量。
gzip on;
gzip_vary on; gzip_proxied any; gzip_comp_level 4; # 压缩级别1-9,4是性价比最高的 gzip_min_length 1k; # 小于1KB的不压缩,压缩比太低 gzip_types text/plain text/css text/javascript application/javascript application/json application/xml image/svg+xml;
关键参数:
- `gzip_comp_level 4`:级别越高压缩比越大但CPU消耗越多。4是个甜蜜点,压缩比已经很可观,CPU开销可接受。
- `gzip_min_length 1k`:太小的内容压缩没意义,压缩后反而可能更大。
- `gzip_types`:一定要把`application/json`加上!API接口返回的JSON数据压缩效果非常好,经常能压缩70%以上。
配置六:连接处理优化
最后这组配置比较零散,但组合起来效果显著:
# 减少不必要的日志写入(高并发时磁盘IO是大问题)
access_log off; # 或者用 buffer
access_log /var/log/nginx/access.log buffer=32k flush=5m;
客户端请求体缓冲
client_body_buffer_size 16k; client_max_body_size 20m;
客户端请求头缓冲
client_header_buffer_size 1k; large_client_header_buffers 4 8k;
重置超时连接,释放资源
reset_timedout_connection on;
关闭不用的功能
server_tokens off; # 隐藏版本号,安全+省带宽
`reset_timedout_connection on` 是个容易被忽视的配置。开启后,当客户端超时断开时,Nginx会发送RST包直接重置连接,而不是走正常的TCP四次挥手。在高并发场景下,大量TIME_WAIT连接会占用资源,直接RST更高效。
完整配置模板
worker_processes auto;
worker_cpu_affinity auto; worker_rlimit_nofile 65535;
events { worker_connections 65535; use epoll; multi_accept on; }
http { sendfile on; tcp_nopush on; tcp_nodelay on;
keepalive_timeout 30s; keepalive_requests 10000;
gzip on; gzip_vary on; gzip_proxied any; gzip_comp_level 4; gzip_min_length 1k; gzip_types text/plain text/css text/javascript application/javascript application/json application/xml image/svg+xml;
client_body_buffer_size 16k; client_max_body_size 20m; client_header_buffer_size 1k; large_client_header_buffers 4 8k;
reset_timedout_connection on; server_tokens off;
# access_log buffer=32k flush=5m;
upstream backend { server 127.0.0.1:8080; keepalive 32; }
server { listen 80; location / { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Connection ""; } } }
压测对比
朋友的服务器是8核16G的云主机,后端是Spring Boot应用:
| 指标 | 优化前 | 优化后 |
| 最大并发连接 | 2,000 | 20,000+ |
| 平均响应时间 | 180ms | 85ms |
| P99响应时间 | 2,100ms | 320ms |
| CPU使用率(2000并发) | 92% | 35% |
| 带宽占用 | 850Mbps | 320Mbps |
带宽占用降了一半多,这就是gzip的功劳。
几点提醒
1. 改配置前先备份。 `cp nginx.conf nginx.conf.bak`,改坏了能回退。
2. 改完先测试。 `nginx -t` 检查语法,没问题再 `nginx -s reload`。
3. 不是所有场景都适合这些优化。 如果你是做上传服务(大文件),`client_max_body_size`要调大;如果是API网关,gzip对JSON的压缩效果比静态文件更好。
4. 系统级参数别忘了。 光改Nginx不够,`sysctl`的`net.core.somaxconn`、`net.ipv4.tcp_max_syn_backlog`、`net.ipv4.ip_local_port_range`也要配套调整。
5. 监控先行。 优化前后都要有压测数据做对比,凭感觉调优等于瞎调。
做IT这么多年,见过太多"早知道就好了"的情况。
希望这篇文章能帮你少走弯路。如果真的遇到问题,别一个人扛着——易云城IT服务随时待命。
📞 服务热线:13708730161 💬 微信:eyc1689 📧 邮箱:service@eycit.com 🌐 https://www.eycit.com
您身边的IT专家。