Nginx的ssl_session_cache在多Worker进程间不自动同步,唯一跨进程共享方式是shared:name:size;builtin、off等均为进程私有,Windows不支持shared会直接报错。

直接说结论:Nginx 的 ssl_session_cache 在多 Worker 进程间不自动同步,唯一能跨进程共享的只有 shared:name:size 类型;其他所有配置(builtin、off、甚至误配的 file)都导致每个 Worker 各自为政,复用率归零。
为什么 shared 是唯一靠谱的跨 Worker 共享方式
Linux/macOS 下,shared:SSL:10m 会触发 Nginx 主进程调用 shm_open() 创建 POSIX 共享内存区,所有 Worker 进程通过 mmap() 映射到同一块物理内存地址。缓存条目不是“复制”,而是所有 Worker 直接读写同一个哈希表槽位——没有网络、没有消息、没有后台同步,纯内存共址访问。
关键点:
- Windows 官方二进制版不支持
shared,配置会直接报错[emerg] invalid value "shared:SSL:10m",只能退回到builtin模式(每个 Worker 独立缓存,互不感知) - 多个
server块若都写shared:SSL:10m,Nginx 会合并为同一块共享区,不是各自分配一份 - 共享内存大小必须在
http块顶层声明,写在server块里等于只对该虚拟主机生效,且无法被其他 Worker 复用
shared 内存大小怎么估才不溢出
共享内存不是越大越好,但太小会导致新会话写不进、被迫全握手。每个缓存条目实际占用约 256–512 字节(取决于证书链长度和 TLS 版本),粗略公式:cache_size ≈ (new_sessions_per_sec × timeout_sec × 0.5KB)。
例如:QPS 2000、ssl_session_timeout 4h(14400 秒),理论峰值需约 2000 × 14400 × 0.5KB ≈ 14GB —— 显然不合理。真实场景中,客户端不会全部卡在超时边缘,建议按 5–30 分钟超时、并预留 2–3 倍冗余来估算:
使用 Playwright 为 jimeng.jianying.com 管理浏览器会话,导入 cookies/localStorage 以自动化视频生成工作流,支持图片上传等功能
- 中小流量(QPS shared:SSL:10m
- 高并发 API 服务(QPS 2000+):直接上
shared:SSL:50m或100m - 别设
ssl_session_timeout超过 1 小时,现代客户端重连频繁,短超时反而提升缓存周转率
builtin 模式在 Linux 上也别乱用
即使在 Linux,ssl_session_cache builtin:1024 仍是每个 Worker 独占一份缓存,总容量 = worker_processes × 1024 条,但复用率随 Worker 数线性下降。比如 8 个 Worker,客户端被轮到不同进程的概率高达 7/8,Session ID 命中率极低。
常见误判:
- 以为
builtin:10000就比shared:10m强——错,builtin最大值受 OpenSSL 内部限制,设太大无效 - 在
http块写builtin:1024,以为能全局生效——其实只是给每个 Worker 都初始化一份 1024 条的缓存 - 没配
ssl_session_timeout,沿用默认 5 分钟,导致缓存刚建好就过期
shared 溢出后根本不会报错,只会悄悄变慢
共享内存满时,Nginx 不会记录 error log,也不会拒绝连接,只是 silently fallback 到全握手。现象是:$ssl_session_reused 变成 .N(not reused)比例陡增、TLS 握手耗时上升、CPU 使用率抬高。
验证手段有限但有效:
- 用
openssl s_client -connect example.com:443 -reconnect多次执行,看输出中Reused, SSL handshake has read 0 bytes and written 0 bytes是否稳定出现 - 配合
stub_status观察Accepts/Handled比值突降(说明更多连接卡在握手阶段) - OpenResty 用户可直接读
ngx.ctx.ssl_session_reused或用ssl_session_fetch_by_lua_block注入日志打点
真正难察觉的是:你改了配置、reload 了 Nginx,但忘了检查是否所有 Worker 都映射成功——主进程分配失败时,Worker 会静默回退到 builtin,而你完全不知道。

















