大带宽服务器Nginx调优:带宽吃到饱但CPU爆表?这10个坑新手必看
前言
大带宽服务器看着香,但很多新手一上来就把带宽跑满,结果CPU直接飙到100%,连接卡死,甚至丢包严重。问题往往出在Nginx默认配置和系统内核参数上。本文直接拆解10个高频陷阱,每个带复现场景+解决方案+验证命令,绝不废话。文中示例基于轻云互联的100Mbps大带宽独立服务器实测,带宽冗余够,但调优不到位照样崩。
1. Socket Backlog太小导致连接排队超时
现象:高并发下Nginx返回`502 Bad Gateway`或`Connection Refused`,`ss -lnt`显示`Recv-Q`堆积。
# 查看当前值
sysctl net.core.somaxconn
# 默认128,大带宽服务器至少改为65535
echo "net.core.somaxconn = 65535" >> /etc/sysctl.conf
sysctl -p
同时Nginx的`listen`指令必须同步增加backlog参数:
server {
listen 80 backlog=65535;
# 若用HTTPS
listen 443 ssl backlog=65535;
}
验证:curl -v --keepalive-time 10 http://your-ip/ 观察建立连接耗时是否<10ms。
2. TIME_WAIT过多耗尽端口——默认吃满内核表
场景:Nginx作反向代理或大量短连接时,`netstat -an | grep TIME_WAIT` 数量轻松破十万。内核端口范围默认32768-60999,只有~28000个,全被TIME_WAIT占满后新连接直接拒绝。
# 优化 sysctl
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_timestamps = 1
net.ipv4.ip_local_port_range = 1024 65535
# 大带宽服务器建议缩小TIME_WAIT存活时间(生产需测试)
echo "30" > /proc/sys/net/ipv4/tcp_fin_timeout
# 或 sysctl
net.ipv4.tcp_fin_timeout = 30
Nginx端开启`reuseport` + 适当调整`worker_connections`:
events {
worker_connections 65535;
reuseport on;
}
3. 内核TCP缓冲区太小——高带宽下吞吐量减半
真实案例:轻云互联100Mbps服务器,默认`rmem_default`=212992,`tcp_rmem`="4096 87380 6291456",导致单流下载只到40Mbps。你需要按带宽计算缓冲区:
# 推荐值(以100Mbps*2倍BDP为例)
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 262144 16777216
net.ipv4.tcp_wmem = 4096 262144 16777216
配合Nginx开启sendfile和directio(对大文件效果明显):
sendfile on;
tcp_nopush on;
# 针对超过4MB的文件使用直接IO
directio 4m;
output_buffers 32 512k;
验证:iperf3 -c server_ip -t 30 -w 2M 看看吞吐能否接近标称值。
4. worker进程与CPU绑定搞错——中断爆发
常见错误:所有worker共享所有CPU,高带宽下网卡中断集中在一个核,导致CPU软中断100%。
# 查看当前中断分布
cat /proc/interrupts | grep eth0
# 设置RPS(Receive Packet Steering)分散中断
echo "f" > /sys/class/net/eth0/queues/rx-0/rps_cpus
# 更狠:使用SMP affinity(需确认驱动支持)
# 先检查网卡支持的队列数
ethtool -l eth0
Nginx的`worker_cpu_affinity`也要跟着绑:
worker_processes auto;
worker_cpu_affinity auto; # 自动绑定到不同CPU
5. 超时配置太刻板——大带宽下慢连接导致worker死循环
坑:默认`keepalive_timeout`=75s,`proxy_read_timeout`=60s。大带宽服务器常对接上游慢源(如数据库),一旦上游响应慢,worker被占满,新请求排队。
# 合理压缩超时,释放worker
keepalive_timeout 10;
keepalive_requests 100;
proxy_connect_timeout 5s;
proxy_read_timeout 10s;
proxy_send_timeout 10s;
同时开启upstream的`keepalive`池减少连接建立开销:
upstream backend {
server 127.0.0.1:8080;
keepalive 256;
}
location / {
proxy_http_version 1.1;
proxy_set_header Connection "";
}
6. 访问日志刷盘锁死磁盘IO
症状:`iostat -x 1`显示磁盘util 100%,但带宽只有30Mbps。访问日志默认每行写一次,大带宽下每秒钟几十万行,直接撑爆。
# 关闭无用日志(如静态资源)
location ~* \.(jpg|png|mp4)$ {
access_log off;
}
# 日志批量写入
access_log /var/log/nginx/access.log main buffer=32k flush=5s;
生产环境建议将日志写入内存盘/dev/shm:
access_log /dev/shm/access.log main buffer=64k;
7. gzip静态文件导致的CPU过载
误区:对所有资源开启gzip。大带宽服务器客户端带宽充足,但CPU弱(比如低端VPS),压缩反而增加延迟。应只对文本类型压缩,且级别设为2:
gzip on;
gzip_min_length 1024;
gzip_comp_level 2;
gzip_types text/plain text/css application/json application/javascript text/xml;
# 不压缩图片/视频
gzip_disable "msie6";
对于静态文件,推荐预压缩:`gzip_static on`配合`gunzip`,省去Nginx实时压缩。
8. 文件描述符限制炸了
翻车现场:`ulimit -n`默认1024,Nginx最大连接=work_connections * worker_processes,大带宽下轻松破万,然后报`too many open files`。
# 修改 /etc/security/limits.conf
* soft nofile 1048576
* hard nofile 1048576
# 然后配置Nginx
worker_rlimit_nofile 1048576;
别忘了重启服务并确认:cat /proc/$(cat /var/run/nginx.pid)/limits | grep 'no file'
9. proxy_buffer过小吞掉上游响应
表现:反向代理返回不完整页面或报`upstream sent too big header`。大带宽服务器常用作中间层代理,默认`proxy_buffer_size` 4k根本不够。
proxy_buffering on;
proxy_buffer_size 16k;
proxy_buffers 8 16k;
proxy_busy_buffers_size 32k;
proxy_temp_path /var/tmp/nginx 1 2;
# 如果上游是fastcgi,同理
fastcgi_buffer_size 16k;
fastcgi_buffers 8 16k;
10. 忽略状态锁——Nginx access/error log vs syslog
冷门坑:日志写入到`/var/log`的文件系统(如ext4)在高并发下会产生inode锁竞争。轻云互联服务器上实测,将日志改道到syslog可降低CPU占用3-5%。
# 安装rsyslog
# Nginx配置
access_log syslog:server=unix:/dev/log,facility=local7,tag=nginx_access,severity=info main;
error_log syslog:server=unix:/dev/log,facility=local6,tag=nginx_error;
配合syslog开启异步写入:rsyslog.conf中`$WorkDirectory /var/spool/rsyslog`,增加`main_queue_size 50000`。
总结
大带宽服务器不是买来就自动跑满的,90%的新手翻车都源于上面10个点。把这套配置跑一遍,配合nginx-tuning-cheatsheet脚本,基本能榨干硬件性能。如果你懒,直接上轻云互联的优化镜像,出厂自带内核+应用层调优,但你至少得知道该往哪看。