关键不是换文件,而是让新连接用新证书握手、旧连接继续用旧证书传输;必须执行nginx -s reload(非restart),配置worker_shutdown_timeout 30s、keepalive_timeout 60s、proxy_read_timeout≥30s,并确保证书路径正确、权限合规、链完整、配置在server块内,再通过ss和openssl实测验证。

更换 SSL 证书时避免服务中断,关键不是“换文件”,而是让新旧连接各司其职:新连接用新证书握手,已有连接继续用旧证书完成传输。Nginx 本身支持平滑重载,但默认行为不保证零中断,必须主动配置协同参数。
核心操作:只 reload,不 restart
执行 nginx -s reload(非 stop/start 或 systemctl restart),它会启动新 worker 进程加载新证书,同时让旧 worker 继续处理未完成的请求。但前提是:
- 新证书文件已覆盖到原路径,且路径与 nginx.conf 中
ssl_certificate和ssl_certificate_key的值完全一致; - 私钥权限为 600(
chmod 600 privkey.pem),证书可为 644; - 执行前务必运行 nginx -t,语法或文件不可读会导致 reload 表面成功、实则回退到旧配置。
必须设置的超时协同参数
仅 reload 不够,旧 worker 若过早退出,正在传输的响应会被 RST 中断。需在 http{} 或 main{} 块中添加:
- worker_shutdown_timeout 30s:强制旧 worker 最多再服务 30 秒(处理完当前请求后退出),这是防止中断的开关;
- keepalive_timeout 60s:避免 reload 前建立的复用连接被 Nginx 主动关闭;
- proxy_read_timeout 和 proxy_send_timeout ≥ 30s:确保代理场景下,旧 worker 不因超时提前丢弃响应;
- ssl_session_timeout 4h:提升 TLS 会话复用率,减少新连接握手开销(不影响 reload)。
证书文件本身要一次到位
常见静默失败不是 reload 问题,而是证书没真正生效:
- 证书链必须完整:把域名证书 + 中间 CA 合并成一个文件(如
fullchain.pem),顺序是“域名证书在前,中间证书在后”; - 路径必须写在
server{}块内,不能放在http{}或events{}中; - 若用 Certbot,务必配置
--deploy-hook "nginx -s reload",避免证书更新了但 Nginx 没重载; - 多节点部署时,统一用软链接(如
/etc/nginx/ssl/current.crt → /etc/nginx/ssl/live/example.com/fullchain.pem),更新只需改链接目标,再同步 reload。
验证是否真平滑
别只信日志,要实测连接生命周期:
- reload 前后执行
ss -tnp | grep :443,观察 ESTAB 连接数应连续下降而非归零; - 对 WebSocket 长连接持续 ping,确认无 1006 错误;
- 用
openssl s_client -connect yoursite.com:443 -servername yoursite.com 2>/dev/null | openssl x509 -noout -dates查看有效期是否已是新证书; - 抓包检查是否有突现的 RST 包,或 error log 中出现
shutdown() failed等提示。











