最近,我们与一家头部的金融科技客户合作,对其核心的跨境支付清算系统进行例行性能评估。该系统的入口是一个基于 OpenResty 构建的高性能 API 网关,每天承载数百亿次调用,峰值 QPS 超过 500,000。在金融科技领域,系统的稳定性和延迟是业务的生命线。他们对关键交易路径的 SLO (Service Level Objective) 有着近乎苛刻的要求。初看之下,系统运行得相当平稳:P50 延迟稳定在 10ms 以内,各项核心指标都处于健康状态。

尽管平均延迟指标表现健康,但深入 P99 延迟曲线,我们发现了一个不容忽视的稳定性风险:周期性出现的尖刺将延迟推高至 300ms 级别,这已经超出了对核心交易路径的严格 SLA 阈值。对于 OpenResty 作为关键网关的系统而言,这不仅是性能衰退的信号,更是潜藏的交易超时风险。

当“地震仪”找不到震源

为客户进行的一次例行性能健康检查中,我们利用 OpenResty XRay 对其生产环境进行了非侵入式的深度扫描。尽管客户现有的监控仪表盘显示系统整体运行平稳,但 OpenResty XRay 的分析很快揭示了两个潜藏在漂亮平均值之下的严重性能风险

  • 无法解释的 P99 延迟: 我们发现,P99 延迟曲线上存在着短暂却高达 300ms 以上的毛刺。这些信号在客户现有的海量监控数据中很容易被当作统计噪音而忽略,但 OpenResty XRay 却能精准捕捉并分析其最长耗时,将其标记为高风险事件。
  • 持续高企的 CPU 黑洞: 监控显示,网关集群的 CPU 利用率,尤其是在 log 阶段,一直居高不下。为了保证峰值时段的稳定性,客户团队不得不采用超额配置的策略,这直接转化为了高昂的基础设施成本。

这是都曾面临的经典难题:大概知道问题出在哪里,大概率是 Lua 代码层,但你不知道具体是哪一行、哪个函数、以及在何种条件下触发。

从经验主义到动态观测的价值转化

很显然,挑战已不再是收集更多的监控数据,而是如何从海量数据中获得可执行的洞察。为了走出“观察-猜测-验证”的低效循环,我们需要一个能够安全地在生产环境进行深度勘察的工具。这正是 OpenResty XRay 发挥核心价值的地方,其非侵入式的动态追踪能力是关键——无需修改任何代码,无需重启任何服务,这对于金融核心系统是不可逾越的红线。

我们在客户一个高负载的生产 Pod 上启动了 OpenResty XRay 的自动分析。几分钟后,第一批深度分析报告生成,谜题的答案开始浮现。

性能热点锁定

P99 毛刺的谜团首先被解开。

  • 证据: OpenResty XRay 的“Regex Expressions”报告清晰地指出,一个 string.gmatch 函数调用,其模式为 "([^%.]+)",在采样周期内的“最长单次执行耗时”达到了惊人的 244.64 ms
  • 根因分析: 这就是 P99 毛刺的直接来源。我们分析后发现,客户团队的工程师习惯性地使用了 Lua 内置的 string.gmatch。这背后的技术原因是,它依赖的 LPeg 引擎并不支持 JIT(Just-In-Time Compilation)。当面对某些边界或恶意构造的输入时,其正则表达式引擎会触发灾难性的性能回溯,导致执行时间瞬间飙升。
  • 解决方案建议: 我们立刻建议客户将热点路径代码中的 string.gmatch 全部替换为 ngx.gmatch。后者基于 OpenResty 深度优化的 PCRE 库,不仅性能更稳定,还支持 JIT 编译。

深层损耗分析

解决了延迟问题,我们把目光转向了 CPU 占用率。

  • XRay 证据: On-CPU 火焰图给出了最直观的线索,ngx_http_log_request 函数栈占用了高达 26.5% 的 CPU 时间。一个本应轻量的 log 阶段,成为了 CPU 消耗大户。
  • 根因分析: 我们下钻火焰图的堆栈,发现对 ngx_http_lua_ffi_compile_regex 的海量调用。这意味着,在 log 阶段用于日志脱敏和格式化的 Lua 代码,正在为每一个请求反复编译同一个正则表达式。这是一个典型但极易被忽略的性能陷阱。
  • 解决方案建议: 根因在于 ngx.re.match 调用时缺少了 'o' (compile-once) 选项。我们建议在所有热点路径(尤其是 log 阶段)的 ngx.re.* 调用中添加 'o' 选项,确保正则表达式“一次编译,无限次运行”。

被遗忘的 PCRE JIT 开关

前两个发现已经带来了巨大价值,但 OpenResty XRay 的“Lua-Land”报告揭示了一个更深层次、更系统性的问题。

  • 证据: 报告显示,客户系统中 所有ngx.re.* 调用,JIT 编译选项都处于关闭状态:即使是我们刚刚建议修复的那些调用。
  • 根因分析: 经过排查,我们发现了一个许多团队都可能犯的错误:客户用于构建网关的基础 Docker 镜像,在编译 OpenResty 时,忘记了添加 --with-pcre-jit 这个关键的编译参数。
  • 解决方案建议: 这意味着整个集群从未享受到 PCRE JIT 带来的巨大性能红利。我们立即建议客户团队重新编译其基础镜像,并在所有 ngx.re.* 调用中统一启用 'j' (JIT) 选项,彻底释放 OpenResty 的潜力。

可量化的工程效率与资源优化指标

基于 OpenResty XRay 的洞察,客户团队实施了一系列优化。效果是立竿见影且可量化的:

  1. P99 延迟毛刺彻底消除: 优化后,P99 延迟曲线变得平滑如镜,从超过 300ms 降至稳定水平。
  2. CPU 成本节约 30%: 修复了正则缓存问题并全局启用 JIT 后,网关集群的整体 CPU 利用率下降了约 30%,节约大量云基础设施成本。
  3. MTTR(平均解决时间)大幅缩短: 性能问题的诊断时间从过去“几周的猜测和会议”,缩短到了“几分钟的精确定位”。

构建持续性能观测能力

修复这两处性能瓶颈的直接价值是显而易见的。但更深层的洞察在于,它再次印证了一个工程哲学:在高并发、低延迟的 OpenResty 环境中,性能问题往往隐藏在构建系统、运行时配置和底层细节的魔鬼之中。

当问题根源超越应用代码逻辑时,传统的观测手段将面临效率瓶颈。缺乏动态、非侵入式的底层追踪能力,即使是经验最丰富的工程师,在面对这些隐蔽的性能回归时,定位成本也会显著提高。

基于这次经历,客户工程团队正审慎地规划下一阶段的工程体系优化。他们计划将 OpenResty XRay 的持续性能分析能力前置,集成到 CI/CD 流程的基准测试环节。在任何可能导致性能退化的代码或配置被合并到主干之前,就能通过自动化的基准测试报告,可靠地捕获环境、配置或编译引起的性能异常。这一举措标志着一种从“被动响应”到“主动防御”的思维转变。

希望这次对 OpenResty 环境中两个典型性能盲区的深度剖析,能够为同样奋战在一线、致力于提升系统稳定性和效率的你,提供一个可借鉴的视角和思路。

关于 OpenResty XRay

OpenResty XRay 是一个动态追踪产品,它可以自动分析运行中的应用,以解决性能问题、行为问题和安全漏洞,并提供可行的建议。在底层实现上,OpenResty XRay 由我们的 Y 语言驱动,可以在不同环境下支持多种不同的运行时,如 Stap+、eBPF+、GDB 和 ODB。

关于作者

章亦春是开源 OpenResty® 项目创始人兼 OpenResty Inc. 公司 CEO 和创始人。

章亦春(Github ID: agentzh),生于中国江苏,现定居美国湾区。他是中国早期开源技术和文化的倡导者和领军人物,曾供职于多家国际知名的高科技企业,如 Cloudflare、雅虎、阿里巴巴,是 “边缘计算 “、” 动态追踪 “和 “机器编程 “的先驱,拥有超过 22 年的编程及 16 年的开源经验。作为拥有超过 4000 万全球域名用户的开源项目的领导者。他基于其 OpenResty® 开源项目打造的高科技企业 OpenResty Inc. 位于美国硅谷中心。其主打的两个产品 OpenResty XRay(利用 动态追踪 技术的非侵入式的故障剖析和排除工具)和 OpenResty Edge(最适合微服务和分布式流量的全能型网关软件),广受全球众多上市及大型企业青睐。在 OpenResty 以外,章亦春为多个开源项目贡献了累计超过百万行代码,其中包括,Linux 内核、Nginx、LuaJITGDBSystemTapLLVM、Perl 等,并编写过 60 多个开源软件库。

关注我们

如果您喜欢本文,欢迎关注我们 OpenResty Inc. 公司的 博客网站 。也欢迎扫码关注我们的微信公众号:

我们的微信公众号

翻译

我们提供了 英文版 原文和中译版(本文)。我们也欢迎读者提供其他语言的翻译版本,只要是全文翻译不带省略,我们都将会考虑采用,非常感谢!