nginx https高并发cpu飙升主因是tls完整握手争抢计算资源,需从握手确认、资源争抢、复用生效三层排查:用perf top定位ssl3_read_bytes等热点函数;openssl s_client检测会话复用率是否低于60%;检查openssl/nginx版本是否支持tlsv1.3;验证worker进程是否绑定同一cpu核;确保ssl_session_cache置于http顶层并设合理超时与票据机制;关闭ocsp stapling及第三方模块排除干扰。

高并发下 Nginx HTTPS 握手引发 CPU 飙高,本质是大量完整握手在争抢有限的 TLS 计算资源——不是连接数太多,而是每次都在重复做高开销运算。排查要从“是否真在握手”“谁在抢资源”“复用有没有生效”三层切入,不靠堆核,而靠精准定位。
确认是不是 TLS 握手本身在吃 CPU
先排除干扰,聚焦真实瓶颈:
- 用 perf top -p $(pgrep nginx | head -1) -g 看热点函数:若 ssl3_read_bytes、EVP_EncryptFinal_ex 或 ecdsa_sign_setup 占比持续高于 20%,说明 TLS 加解密或签名是主因
- 执行 openssl s_client -connect your.site:443 -reconnect 2>/dev/null 2>&1 | grep "Reused":输出中“Reused, SSL handshake succeeded”比例长期低于 60%,说明会话复用基本失效,大量连接被迫走完整握手
- 检查 nginx -V | grep ssl:OpenSSL 版本低于 1.1.1 则无法启用 TLSv1.3,握手开销难以下降;Nginx 版本低于 1.13.0 同样不支持 TLSv1.3
查 worker 进程是否在无约束争抢 CPU 核
多个 worker 绑定到同一物理核心(PSR),会导致 TLB miss、缓存失效和跨核迁移开销激增:
- 运行 ps -eo pid,psr,comm | grep 'nginx: worker' | sort -k2,2n:若多个 PID 显示相同 PSR 编号,就是绑定冲突
- 用 pidstat -t -p $(pgrep nginx) 1 观察线程级负载:某 CPU 核上多个 nginx 线程持续占用超 80%,即为典型争抢信号
- 必须配置 worker_processes auto; 和 worker_cpu_affinity auto;,并确保系统 ulimit -n ≥ 65536、net.core.somaxconn ≥ 65535
验证会话复用配置是否真正跨进程生效
复用失效,90% 的优化都白做。关键不在 server 块里加几行,而在 http 块顶层构建统一上下文:
- ssl_session_cache shared:SSL:20m; 必须写在 http { } 最外层——写在 server 或 location 里,各 worker 自建缓存,无法共享
- ssl_session_timeout 4h;:默认 5 分钟太短,移动端切后台再唤醒、HTTP/1.1 短连接基本错过复用窗口;设为 4 小时兼顾内存与用户行为周期
- ssl_session_tickets on; + ssl_session_ticket_key /etc/nginx/ssl/ticket.key;:客户端存票据,服务端压力更小;密钥建议每月轮换,权限设为 400 且仅主进程可读
排除 OCSP Stapling 和第三方模块干扰
OCSP 响应失败或模块 SSL 回调异常,会导致 worker 阻塞或内存堆积,间接放大 CPU 压力:
- 临时关闭 ssl_stapling off; 并重启,观察 error_log 中是否还有大量 ngx_ssl_stapling_cert_t 相关警告,或内存增长趋势是否减缓
- 检查是否加载了 Lua、ModSecurity、自定义证书校验等模块;若有,尝试禁用后对比 worker 内存/CPU 行为
- 启用 debug 日志:error_log /var/log/nginx/ssl_debug.log debug;,筛选含 ssl handshake、no shared cipher、version too low 的条目——高频出现说明客户端兼容性差,频繁重试加重竞争











