ssl_session_cache是HTTPS性能优化最直接有效的手段,通过复用会话状态大幅削减TLS握手CPU开销,推荐使用shared:SSL:10m配合ssl_session_timeout 4h、ssl_session_tickets on及定期轮换的ticket.key。

会话缓存(ssl_session_cache)是 HTTPS 性能优化中最直接有效的手段之一,它不改变协议、不升级硬件,却能大幅削减 TLS 握手带来的 CPU 开销——尤其在 API 服务、前端资源加载、移动端频繁重连等场景下,效果立竿见影。
为什么握手损耗高?缓存如何“绕过”它
TLS 完整握手(Full Handshake)需执行密钥交换(RSA/ECC)、证书验证、随机数协商等密集计算,单次 CPU 耗时可达毫秒级;而复用已有会话(Session Resumption)只需验证会话 ID 或解密票据,耗时下降 70% 以上。
ssl_session_cache 就是把成功握手生成的会话状态(如主密钥、加密套件、证书链片段)暂存在内存中,供后续连接快速检索复用。关键点在于:
- 它作用于 TLS 层,与后端应用(Java HttpSession / Node.js session)完全无关
- 复用成功与否,取决于客户端是否携带有效会话 ID 或 ticket,以及服务端是否还保留对应缓存
- 没有缓存,每次新连接都触发完整握手;有缓存且命中,握手退化为简短的 Session-ID 或 Ticket 复用流程
shared 缓存才是生产环境唯一合理选择
Nginx 支持 builtin(每个 worker 私有)和 shared(多 worker 共享)两种模式。但 builtin 在真实部署中基本无效:
- Linux 默认使用 accept_mutex 或 SO_REUSEPORT,连接被随机分发到不同 worker
- 客户端重连落到 A worker,而会话缓存在 B worker,复用失败
- 即使配置
builtin:1000,实测复用率通常低于 5%,形同虚设
必须使用 shared:SSL:10m 这类共享内存配置,让所有 worker 进程读写同一块内存区域。1MB 共享内存约可存 4000 个会话(受证书链长度、TLS 版本影响),10m 即支持数万个活跃会话。
容量与超时:两个参数必须协同调优
光配 shared:SSL:10m 不够,还需匹配合理的 ssl_session_timeout:
- 默认 5 分钟太短:用户切网络、APP 后台唤醒、HTTP/2 连接空闲后重用,常已超时
- 推荐值:普通站点设
10m–20m;内网网关或可信环境可设4h(14400 秒) - 超时设长了,缓存容量必须跟上,否则会因满而提前淘汰——可用公式粗估:
所需内存(MB) ≈ 新建会话数/秒 × 超时秒数 × 0.5KB ÷ 1024 - 例如峰值 800 次新握手/秒、timeout=4h → 约需 8.4MB → 直接配
shared:SSL:10m起步
启用 session ticket:无状态兜底,双保险架构
仅靠 shared 缓存仍有局限:旧客户端(如 Android 4.x)只认 Session ID;高并发下缓存溢出时,复用率断崖下跌。
开启 ssl_session_tickets on 并配置密钥文件,可启用 RFC 5077 的会话票据机制:
- 票据由客户端自行加密携带,服务端无需存储会话状态,彻底规避内存压力
- 必须配合
ssl_session_ticket_key /etc/nginx/ssl/ticket.key使用(二进制文件,≥32 字节) - 建议每月轮换 ticket.key,防止长期密钥泄露导致会话被重放
- 现代浏览器(Chrome/Firefox/iOS)默认优先使用 ticket,复用率远高于 session ID
怎么确认它真起作用了?别只看配置
配置写对 ≠ 效果落地。验证必须基于实际行为:
- 用 OpenSSL 命令压测:
openssl s_client -connect example.com:443 -reconnect -servername example.com 2>/dev/null | grep "Session-ID\|Reused"
若多次输出中Reused: Yes频繁出现,说明复用生效 - 在 Nginx 日志中加入
$ssl_session_reused变量,统计r(复用)与.(未复用)比例,目标复用率 ≥ 80% - 观察系统指标:启用后 TLS 握手平均耗时应明显下降,CPU sys 时间占比降低,
nginx -s reload后 RSS 内存增长平缓而非飙升


















