Nginx 在 Ubuntu 上的性能瓶颈定位方法
一、快速定位流程
- 明确瓶颈类型:是 CPU、内存、磁盘 I/O、网络带宽,还是 后端应用(如 PHP/Python/Java) 或 连接数/文件句柄 限制。
- 复现与压测:用 ab/wrk 在另一台机器持续施压,保持压力稳定,便于观测与采样。
- 资源面观测:用 top/vmstat/pidstat/sar 看整体与进程维度的 CPU、内存、I/O、上下文切换、软中断 等。
- 热点定位:对可疑进程用 perf top -g -p 或 火焰图 找到函数级热点。
- Nginx 面观测:启用 stub_status 看连接与请求;打开 access_log 的 $request_time/$upstream_response_time 定位慢请求;必要时用 ngxtop 实时分析日志。
- 网络与连接:用 ss -s/ethtool -S 看 TCP 连接数、重传、丢包、带宽;检查 文件句柄 是否触顶。
- 结论闭环:把“现象—指标—位置—证据(火焰图/日志/抓包)—可复现步骤”串起来,再决定优化手段。
二、关键指标与工具对照表
| 现象 |
优先看什么 |
快速命令 |
进一步定位 |
| CPU 高 |
用户态/系统态占比、软中断 |
top/vmstat 1、pidstat -u 1、sar -P ALL 1 |
perf top -g -p 、火焰图 |
| 负载高但进程 CPU 不高 |
软中断 si、上下文切换 |
top 看 %si、vmstat 1 看 cs |
sar -n SOFTIRQ/DEV 1、网络抓包 |
| 内存紧张/抖动 |
可用内存、swap、缓存命中 |
free -m、vmstat 1 |
smem、pmap |
| 磁盘 I/O 慢 |
await、svctm、util |
iostat -x 1 |
lsof + strace 看具体文件/进程 |
| 连接数不够/排队 |
连接队列、TIME_WAIT |
ss -lntp、netstat -s |
sysctl -a |
| 带宽打满 |
出/入带宽、重传 |
sar -n DEV 1、ifstat、ping/ethtool |
iperf3 测端到端带宽 |
| 后端慢 |
upstream 时延 |
access_log 加 $upstream_response_time、$request_time |
ab/wrk 对比有无代理的差异 |
| 句柄不够 |
打开文件数 |
ulimit -n、cat /proc//fd |
limits.conf、worker_rlimit_nofile |
三、CPU 与内核态热点的定位
- 用 top 按 1 展开每个 CPU,观察 %us、%sy、%wa、%si;若 %us 高,多为用户态计算密集;%sy 高,多为系统调用/内核路径;%wa 高,多为 I/O;%si 高,多为软中断(网络收包等)。配合 pidstat -u 1 找出具体进程。若整体 CPU 高但各进程都不高,常见于 短任务频繁唤醒/软中断 场景,应重点查 si 与网络栈。
- 对可疑进程(如 php-fpm/nginx)采样热点函数:执行 perf top -g -p ,按 Enter 展开调用栈,定位到具体函数(如某计算函数或系统调用)。必要时用 perf record -g -p -o perf.data 生成数据后用火焰图分析。
- 若遇到“系统 CPU 很高但找不到高 CPU 进程”的情况,优先检查 软中断(si)、内核线程 与 短周期任务风暴,并结合 sar -n SOFTIRQ/DEV 与网络抓包进一步确认是否为网络收包/协议栈处理导致。
四、Nginx 与应用层面的定位
- 打开 http_stub_status_module 观察 Active/Reading/Writing/Waiting 等关键计数,判断是否因 连接数/等待队列 受限。
- 自定义 access_log,加入 $request_time、$upstream_response_time、$status、$body_bytes_sent,用 awk/sort/uniq 或 ngxtop 找出 P95/P99 时延 最高、返回码异常、流量异常的接口或来源。
- 区分 静态资源 与 动态接口:静态资源瓶颈多在 磁盘 I/O/带宽;动态接口瓶颈多在 后端处理(CPU/数据库/缓存)。对动态接口,优先看 upstream_response_time 是否显著大于 request_time,若是,问题多在后端。
- 长连接与头部开销:开启 keepalive(如 keepalive_timeout 65s)复用连接,减少握手开销;启用 gzip 减少传输字节;静态资源开启 sendfile on; tcp_nopush on;(按需)提升传输效率。
五、系统与网络瓶颈的定位
- 文件句柄与进程限制:检查 ulimit -n 与 /proc//fd 是否触顶;在 /etc/security/limits.conf 或 systemd 服务单元中提升 nofile,并在 Nginx 配置中设置 worker_rlimit_nofile 与 worker_connections,确保 worker_processes × worker_connections 能满足并发需求。
- TCP 连接与端口:用 ss -s 看 ESTAB、TIME_WAIT 数量;netstat -s 看重传与失败;必要时调优 somaxconn、tcp_tw_reuse/tcp_tw_recycle(注意版本与场景差异)、backlog 等内核参数。
- 带宽与丢包:用 sar -n DEV 1、ifstat、ping/ethtool -S 观察 bps、pps、丢包、错包;跨机房/跨地域可用 iperf3 测端到端带宽与抖动。
- 磁盘与 I/O:用 iostat -x 1 看 await、svctm、util;若 util≈100% 且 await 高,多为磁盘瓶颈;结合 lsof/strace 定位具体文件/进程。
- 压测与对比:用 ab/wrk 做基线(如 ab -c 100 -n 1000),对比“直连后端 vs 经过 Nginx”的 RPS、P95/P99、失败率,确认瓶颈是在 Nginx 还是后端。