应使用 shared 缓存实现多 worker 进程共享 SSL 会话,避免 builtin 私有缓存因连接分发随机导致复用率极低;容量需按“每秒握手数 × 会话超时 × 单条开销”估算,普通站点从 5m 起步,高 QPS 或长证书链场景需上调至 20m 或更高,并通过 $ssl_session_reused 统计复用率与内存使用率调优。

shared:SSL: 的容量怎么算才不浪费也不溢出
直接按「每秒握手次数 × 会话平均存活时间 × 单条会话内存开销」估算,比拍脑袋设 10m 更靠谱。Nginx 官方文档没给固定值,但实测 1MB 共享内存约存 4000 个会话(取决于证书大小、TLS 版本、是否启用 OCSP Stapling)。如果站点每秒新建 500 个 HTTPS 连接,ssl_session_timeout 设为 4h(14400 秒),理论峰值会话数是 500 × 14400 = 7.2M 条——但这明显高估,因为大量连接不会同时活跃。
更贴近生产的方式是:用 nginx -T | grep ssl_session_cache 确认当前配置,再结合日志里 $ssl_session_reused 变量统计实际复用率。若复用率长期低于 60%,大概率是缓存太小被频繁淘汰;若 free -m 显示 shared 内存使用率长期低于 20%,说明分配过量。
- 普通 Web 站点(QPS ≤ 100):从
shared:SSL:5m起步,观察 24 小时复用率 - API 网关 / 前端资源服务(QPS ≥ 500):建议
shared:SSL:20m,并开启ssl_session_tickets on分摊压力 - 证书链很长(比如含中间 CA + OCSP 响应缓存):单条会话内存可能达 3–4KB,此时 10m 实际只能存约 2500–3300 条,需按比例上调
builtin 和 shared 混用时,为什么 builtin 几乎没用
builtin 是每个 worker 进程私有缓存,比如 builtin:1000 表示该 worker 最多存 1000 条。问题在于:客户端重连不保证落到同一个 worker,尤其在 Linux 的 accept_mutex 关闭或使用 SO_REUSEPORT 时,连接分发更随机。结果就是 A worker 缓存了会话,B worker 收到重连请求却查不到,只能走完整握手。
除非你明确知道流量会被绑定到单个 worker(比如用 worker_cpu_affinity + SO_REUSEPORT 配合负载均衡器做 sticky session),否则 builtin 对复用率提升几乎为零。它响应快,但不解决跨进程一致性问题——而这就是 shared 存在的意义。
- 调试阶段可临时加
builtin:500辅助验证 handshake 流程,但上线必须依赖shared - 混用写法如
ssl_session_cache builtin:500 shared:SSL:10m是合法的,但builtin部分基本闲置 - 某些旧版 Nginx(shared 初始化失败时会 fallback 到
builtin,但现在已极少遇到
ssl\_session\_timeout 不是“保质期”,而是“最后活跃时间窗口”
ssl_session_timeout 4h 并不意味着会话一定活满 4 小时。它指“从该会话最后一次被复用起,4 小时内未再被访问,就自动清理”。所以高频访问的会话可能持续数天,而冷门会话几分钟就被踢出。这也是为什么单纯调大 timeout 不一定能提升复用率——如果用户连接间隔远超 timeout,再大的值也没用。
真正影响复用率的是客户端行为:移动端切网络、浏览器标签页休眠、HTTP/2 连接空闲超时(keepalive_timeout)早于 ssl_session_timeout,都会导致会话失效。因此必须协同调整:
使用 Playwright 为 jimeng.jianying.com 管理浏览器会话,导入 cookies/localStorage 以自动化视频生成工作流,支持图片上传等功能
-
keepalive_timeout至少 ≥ssl_session_timeout,否则连接先断,会话白存 - 移动端场景下,
ssl_session_timeout设为 10m–30m 更现实,别迷信 4h - 若用 HTTP/2,注意
http2_max_requests默认 1000,到达后连接强制关闭,也会打断复用
验证复用是否真生效,别只看 openssl 输出
openssl s_client -connect example.com:443 -reconnect 看 Reused: Yes 是基础,但它只反映单次重连,且受本地网络环境干扰大。真实瓶颈往往藏在日志和指标里。
最有效的验证方式是打开 Nginx 日志变量:$ssl_session_reused。它输出 .(未复用)或 r(复用),配合 log_format 统计比例:
log_format ssl_reuse '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'ssl_reused=$ssl_session_reused';
然后用 awk 或 Prometheus 抓取 r 出现频率。若线上复用率长期低于 50%,优先检查 shared 大小、ssl_session_tickets 是否开启、以及客户端 TLS 栈是否支持 session ticket(Android 4.x 以下、老版 IE 不支持)。
容易被忽略的一点:即使配置全对,如果上游用了 CDN 或四层 LB,且它们终止了 TLS(即 SSL offloading),那 Nginx 根本收不到原始 TLS 握手,ssl_session_cache 完全不生效。










