ssl_session_cache缓存单位是会话槽而非字节,10m共享内存按144字节/槽约分7.2万个槽位,需据峰值HPS、实测会话寿命及冗余系数精准计算槽需量,并监控$ssl_session_reused与stub_status指标验证效果。

ssl_session_cache 的缓存单位不是字节,而是会话槽(session slot)
很多人误以为 ssl_session_cache 的大小参数(比如 10m)直接对应可缓存的会话数量,其实它表示的是共享内存块的总字节数,而每个会话槽实际占用约 128–160 字节(取决于 OpenSSL 版本和启用的扩展,如 OCSP stapling)。OpenSSL 1.1.1+ 默认一个槽占 144 字节左右。
所以 ssl_session_cache shared:SSL:10m 并不等于“存 10MB 会话数据”,而是分配一块 10MB 的共享内存,Nginx 会按固定槽大小切分成约 10 * 1024 * 1024 / 144 ≈ 72,000 个槽位。超出槽位数后,新握手会触发 LRU 驱逐——但驱逐本身有开销,且频繁驱逐会导致缓存命中率骤降。
- 用
nginx -V 2>&1 | grep -o 'OpenSSL [0-9.]+'确认 OpenSSL 版本,再查对应文档确认单槽尺寸 - 生产环境建议预留 20% 槽位冗余,避免刚好卡在阈值附近抖动
- 不要盲目设成
100m:过大的共享内存块会增加锁竞争,尤其在多 worker 进程高并发场景下,反而降低吞吐
每秒握手次数(HPS)怎么算?别只看 access.log
access.log 里的 TLS 握手无法直接统计,因为 HTTP 请求可能复用已有连接(keepalive),而真正触发完整握手的是 SSL handshake 事件,需从 Nginx 的 stub_status 或自定义日志中捕获。
更可靠的方式是开启 Nginx 内置变量统计:$ssl_handshake_time 只在完整握手时非空,配合 log_format 记录;或用 stub_status 的 Active connections + accepts 差值粗估——但后者含非 SSL 连接,误差大。
- 推荐方案:在 log_format 中加入
'$ssl_protocol:$ssl_cipher:$ssl_handshake_time',用日志采样分析每秒非空$ssl_handshake_time出现频次 - 注意区分 full handshake 和 session resumption:只有 full handshake 才消耗槽位,resumption 不占新槽
- 高峰期 HPS 峰值要取 5 秒滑动窗口最大值,而非平均值——缓存不足问题总发生在瞬时尖峰
缓存大小 = HPS × 平均会话生命周期 × 安全冗余系数
会话默认超时由 ssl_session_timeout 控制(默认 5m),但真实生命周期受客户端行为影响更大:移动设备常主动断连,CDN 回源可能提前关闭连接。实测中,有效生命周期往往只有 60–180 秒。
使用 Playwright 为 jimeng.jianying.com 管理浏览器会话,导入 cookies/localStorage 以自动化视频生成工作流,支持图片上传等功能
公式:所需槽位数 ≈ HPS_peak × T_effective × 1.5(1.5 是防抖冗余)。例如峰值 HPS=300,实测平均存活 90 秒 → 需约 40,500 槽,按 144 字节/槽 → 约 5.8MB,向上取整到 10m 更稳妥。
-
ssl_session_timeout设太长(如 4h)会让槽位长期被无效会话占据,反而降低命中率 - 如果使用
ssl_session_cache builtin:1000(非共享),它只作用于单个 worker,无法跨进程复用,高并发下等同于没开缓存 - 启用
ssl_buffer_size(如 4k)可减少 TLS 分片,间接降低握手频率,但对缓存大小无直接影响
验证是否调优到位:看 $ssl_session_reused 变量和共享内存使用率
光看响应时间没用。关键指标是 $ssl_session_reused —— 它为 Y 表示本次连接复用了缓存会话,为 . 表示 full handshake。理想情况下,线上服务该值应稳定在 85% 以上。
同时,用 curl http://127.0.0.1/nginx_status(需启用 stub_status)观察 SSL cache misses 和 SSL cache hits 的比值。若 miss/hit > 0.15,说明槽位严重不足;若 hit 接近 100% 但内存使用率长期
- 注意:
stub_status的 SSL 统计项在较老 Nginx 版本(shdict 手动埋点 - 某些 CDN 或 LB 会在前端终止 TLS,此时后端 Nginx 的
$ssl_session_reused恒为.,调优失去意义——先确认 TLS 终止点在哪 - 动态扩容不现实:修改
ssl_session_cache大小必须 reload Nginx,且旧共享内存不会自动释放,需滚动重启
缓存大小不是越大越好,也不是越接近理论值越稳;真实瓶颈常藏在 OpenSSL 版本差异、客户端重用策略、以及你根本没意识到的 TLS 终止位置里。

















