在大型 NGINX 配置中降低 TLS 资源与重载成本

在大型 NGINX 配置中降低 TLS 资源与重载成本

作者:Aleksei Bavshin(NGINX Community Blog) 来源:原文

流程图: 父级 TLS 上下文 -> 单周期 SSL 对象缓存 -> 跨重载复用 -> 变量证书 LRU 缓存
流程图: 父级 TLS 上下文 -> 单周期 SSL 对象缓存 -> 跨重载复用 -> 变量证书 LRU 缓存 (本稿自绘示意图)

从重复初始化开始找成本

NGINX 配置的 server/location 上下文默认各自处理。指令值可继承,但 OpenSSL 的 SSL_CTX 等复杂对象通常会重新创建。大量虚拟主机反复引用相同证书、私钥和 CA 列表时,配置加载时间就被重复读取与解析放大。把父级已定义且未在子级重写的 TLS 指令向下继承,是第一层优化;只要在 location 重复写出相关指令,即使参数看起来相同,优化也可能失效,因为逐项比较配置值本身有成本。

第一项单周期 SSL 对象缓存随 NGINX 1.27.2 发布;第二层把证书、私钥、CRL 等 OpenSSL 对象在一次完整配置加载周期内缓存。对象本身可引用计数,NGINX 只需在读取请求处查找并复用解析结果。该改动跨 OpenSSL 版本及其他 TLS 库,需要保留各实现差异;因此应按具体 NGINX 发行版和动态模块组合核对,而不能把“用了缓存”当成无需回归测试。

原文基准图给出配置加载内存和 retired instructions 相对于唯一 SSL 对象比例的变化,并对比 NGINX 1.27.1 与 1.27.2。图中基线数据来自原作者的环境与配置,曲线只说明该测试条件下的变化趋势。原作者的结论是,配置加载成本和内存占用随唯一 SSL 对象数变化,而不是随总引用数变化;内存的轻微额外开销从约 90% 唯一性开始。

原文配置加载基准图:横轴为唯一 SSL 对象比例 0–100%;左图是内存使用(MB),右图是 retired instructions,对比 NGINX 1.27.1 与 1.27.2。1.27.1 曲线基本水平,1.27.2 随唯一对象比例上升。
原文图:配置加载内存与 retired instructions。作者 Aleksei Bavshin,NGINX Community Blog,© F5, Inc.,原文。这是原文历史基准图,不是本次运行或复现结果。

跨重载复用要看可验证的身份

后续跨重载复用与变量证书缓存随 NGINX 1.27.4 发布。每次重载会建立一套新的完整配置实例,但大部分文件和对象往往未变。字面量 data: 对象以完整内容作查找键,可以安全复用;engine: 引用外部密钥存储,NGINX 无法判断外部内容是否变化,因此只在单次配置周期缓存。普通文件则按修改时间和 inode 重新验证,两者均未变才沿用旧对象;无法取得元数据时按已变处理并重新载入。加密私钥不跨重载复用,以免密钥进入未配置相应 ssl_password_file 的上下文。

若必须取消重载间继承,可在顶层设 ssl_object_cache_inheritable off。它描述“本次载入配置是否供下一次重载继承”,所以设置后至少还要再重载一次(或完整重启)才能清掉先前缓存。文中性能测试使用 10,000 个 location,分别测退休指令数和 mallinfo2 内存增量;实验机器为 Dell PowerEdge M630(Intel Xeon E5-2650 v3)、Ubuntu 24.04 LTS、OpenSSL 3.0.13,源文还称 OpenSSL 3.4 的内存表现有改进。结果随唯一证书数量与库版本而变,不是按 location 数线性变化的通用保证。

变量证书缓存与适用边界

变量型 ssl_certificate 允许按请求或域名惰性加载不同证书,但每次 TLS 握手的开销会比静态证书路径高,短连接更容易感知。NGINX 1.27.4 引入 ssl_certificate_cache max=N [inactive=time] [valid=time]。max 限制缓存条目数,溢出时按 LRU 淘汰;证书和私钥分别占一项。inactive 控制多久未访问后移除(当前文档默认 10 秒),valid 控制多久后重新载入或验证(当前文档默认 60 秒)。缓存可在 http 级继承,也可按 server 设置或关闭;这些默认值仍需以目标版本文档为准。proxy_ssl_certificate_cache、grpc_ssl_certificate_cache 和 uwsgi_ssl_certificate_cache 分别覆盖相应上游认证场景。

测试文章用单 worker、关闭 TLS session tickets 和 keepalive,刻意制造每个请求重新握手的最坏条件;不能照抄成生产调优。本文整理保留了原文版本和元数据复用条件,并将“提高资源效率”限定为重复对象较多的配置。上线前先对证书轮换、权限、失效窗口、重载回退做验证。

原文还比较 NGINX 1.27.4 在 OpenSSL 1.1.1、3.0.13 和 3.4.0 下的每秒请求数(RPS),并分别测试静态证书、带缓存的动态证书与未缓存的动态证书。原作者报告,启用动态证书缓存后,RPS 几乎回到静态证书对的水平。图中数值只代表作者报告的基准环境;不同 OpenSSL 版本、证书和请求模式会明显改变结果。

NGINX 1.27.4 原文 RPS 柱状图,按 OpenSSL 1.1.1、3.0.13、3.4.0 分组,比较 TLS 1.2 与 1.3 下静态证书、动态证书缓存和动态证书无缓存。
原文图:静态和动态证书缓存的 RPS 对比。作者 Aleksei Bavshin,NGINX Community Blog,© F5, Inc.,原文。图示为作者历史基准,不是本次运行或复现结果。

静态核对范围

本文只对照原文、当前官方模块文档和静态配置片段;没有执行 nginx -t,加载或重载任何 NGINX 配置,也没有运行性能基准。两幅图中的数据是作者报告的历史结果,不是本文运行结果。

来源与许可说明

NGINX Community Blog 原文页面未标明适用于全文的开放内容许可证;文章与两幅原始基准图的版权归其权利人。本译稿及原文图依据另行取得的授权使用,保留作者、来源和 © F5, Inc. 标记,不将它们标为开放许可。本稿自绘流程图与原始数据图分开标注。

本文为中文译写稿,原文:https://blog.nginx.org/blog/optimizing-resource-usage-for-complex-ssl-configurations。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容