SSL会话缓存过小会导致频繁完整握手,显著增加CPU和延迟;需检查shared缓存大小(如10m是否足够)、timeout设置(推荐4h但需适配客户端行为),并结合debug日志、openssl复用测试及$ssl_session_reused等指标验证命中率。

SSL 会话缓存过小会导致 Nginx 在高并发下频繁触发完整 TLS 握手(而非复用缓存的会话),显著增加 CPU 开销和延迟。排查需结合配置、指标和实际连接行为综合判断。
检查当前 SSL 会话缓存配置是否合理
Nginx 默认的 ssl_session_cache 很可能不适用于生产流量。重点关注两个参数:
-
缓存大小:如
ssl_session_cache shared:SSL:10m,10MB 约可缓存 4000–6000 个会话(取决于证书长度和 TLS 版本)。若每秒新建 HTTPS 连接数持续 >500,10m 容易被快速填满并淘汰旧条目。 -
超时时间:
ssl_session_timeout 4h是常见值,但若客户端重连周期短(如移动端 App 每分钟心跳),过长 timeout 反而导致缓存被无效会话占满;过短(如 1m)则复用率骤降。
观察 Nginx 自身指标验证缓存命中率低
启用 stub_status 或使用 OpenResty 的 nginx-module-vts,关注关键指标:
-
SSL handshake rate:通过
nginx -V 2>&1 | grep -o with-http-stub-status-module确认模块已编译,再在 server 块中配置location /nginx_status { stub_status; }。访问该地址,观察Active connections和Reading/Writing/Waiting中与 SSL 相关的抖动趋势。 -
更直接的方式是开启 error_log 调试级日志:
error_log /var/log/nginx/ssl_debug.log debug;,并过滤关键词:grep "SSL_do_handshake" /var/log/nginx/ssl_debug.log | tail -n 1000 | wc -l。若单位时间内完整握手次数接近新建连接数,说明几乎无复用。
用 OpenSSL 模拟验证会话复用行为
手动测试能快速确认服务端是否愿意复用会话:
- 第一次连接并保存会话:
openssl s_client -connect example.com:443 -reconnect -servername example.com 2>/dev/null | grep "Session-ID" - 第二次连接尝试复用(加
-sess_out/-sess_in):openssl s_client -connect example.com:443 -sess_in session.pem -servername example.com 2>/dev/null | grep "Reused, SSL"。若输出中没有Reused, SSL,且返回Session-ID: 0000...(新 ID),说明服务端未复用——可能是缓存满、超时、或客户端 SNI 不一致。
对比优化前后的效果
调整后不要只看平均延迟,重点观察 P95/P99 TLS 握手耗时(可通过 access_log 中 $request_time 与客户端日志比对,或用 eBPF 工具如 bpftrace 抓取 ssl:ssl_set_session 事件)。典型改善表现为:
- 完整握手占比从 >80% 降至
- 单核 CPU 的
%sys时间下降(因内核 crypto 调用减少) - access_log 中
$ssl_protocol和$ssl_cipher字段稳定,而$ssl_session_reused字段中r(reused)比例明显上升
不复杂但容易忽略:缓存大小不是越大越好,需结合内存占用与预期并发连接生命周期平衡;同时确保所有 upstream 或 LB 后端的 SSL 缓存配置一致,避免因多节点间无共享导致整体复用率虚高。



















