华为云 APIG 开放 API 网关在后端服务升级期间的 502 排障:超时、熔断、灰度回退三线定位

举报
yd_260132607 发表于 2026/11/08 09:41:26 2026/11/08
【摘要】 一、问题现场我们有一批对外接口挂在华为云 APIG 开放 API 网关后面,后端是 CCE 上的微服务。这周做了一次后端服务的滚动升级,升级本身在 CCE 侧看是成功的,Pod 全部 Ready,滚动过程中也没有任何镜像拉取失败。但升级窗口内的十几分钟里,外部调用方陆续报 502,网关控制台的"访问日志"里错误码集中在 502 和 504 两类,而"API 调用统计"上 QPS 曲线出现了一...

一、问题现场

我们有一批对外接口挂在华为云 APIG 开放 API 网关后面,后端是 CCE 上的微服务。这周做了一次后端服务的滚动升级,升级本身在 CCE 侧看是成功的,Pod 全部 Ready,滚动过程中也没有任何镜像拉取失败。但升级窗口内的十几分钟里,外部调用方陆续报 502,网关控制台的"访问日志"里错误码集中在 502 和 504 两类,而"API 调用统计"上 QPS 曲线出现了一个明显的凹坑。更让人困惑的是,同样的客户端、同样的参数,在升级窗口之外的任何时刻都没复现过。

一开始我们怀疑是 CCE 的 Pod 摘流没做干净——毕竟滚动升级时旧 Pod 终止和新 Pod 就绪之间天然有空窗。于是把摘流时间从 30 秒拉到 120 秒,把 preStop 钩子加长。结果第二轮升级时 502 依然出现,而且时间点几乎和第一轮一模一样。这说明问题不在"摘流慢"这一层,必须换个方向查。

二、第一条线:把 502 和 504 分开看

这次排查真正的转折点,是把错误码分开统计。很多人在看网关错误率的时候会把所有 5xx 混在一起,但 502 和 504 的含义完全不同:

  • 504 是网关自己产生的,语义是"我按配置的超时时间等后端,后端没在期限内返回"。这类问题的后端其实可能是好的,只是慢。
  • - 502 是网关拿到了后端的响应,但那个响应不是合法的上游响应,或者连接在传输过程中被异常终止了。

我们把升级窗口内的全部 5xx 请求按这两个码拆开,发现分布非常稳定:504 占绝大多数,502 只占很小一撮,而且这少量 502 全部落在升级刚开始的那 90 秒内,之后再没出现过。

这个分布本身就给了很强的信号:如果问题出在 CCE 摘流或者注册中心路由,502 应该和 504 均匀地出现在整个窗口,而不是集中在最开始那一小段。于是我们把注意力从"后端 Pod 的生命周期"挪到了"网关的上游连接管理"上。

三、第二条线:后端确实慢了,但慢的原因被上游掩盖了

顺着 504 往下查,我们去看了后端服务的这段时间的实际耗时。结果发现后端 P99 从 40 毫秒涨到了 3 秒多,个别请求到了 8 秒。这个耗时在业务上是异常的,但服务本身没有任何异常日志,也没有 GC 停顿、没有连接池耗尽的迹象。

真正的元凶在下游依赖:升级后的新版本把一个原本"每请求查一次"的配置查询,改成了"每次请求都去远程拉取"。这个远程拉取走的是一个内部服务,而内部服务在这个时间段恰好因为同样的升级动作在做自己的实例切换,响应时间被拉到了秒级。于是形成了一个典型的级联放大:一次升级 → 下游依赖短暂变慢 → 上游服务 P99 从毫秒级掉到秒级 → 网关按 1 秒超时切断 → 504。

这里有个很值得记下来的点:APIG 的超时配置如果设置得比后端服务的实际 P99 还短,那么网关会持续地把"后端慢"翻译成"网关超时"。排查时如果只看网关的错误日志,会一直以为问题在网关;必须同时看后端自身的耗时分布,才能知道超时阈值是不是合理。我们后来把这条链路的超时从 1 秒调整为 5 秒,同时把那个每请求都远程拉配置的行为改回带本地缓存。

四、第三条线:那少量 502 是什么

集中于升级最初 90 秒的少量 502,需要单独解释。我们的判断是:旧 Pod 在收到 SIGTERM 之后,正在处理中的 HTTP/2 长连接被直接关闭,但网关侧的连接池还持有这些连接的下一次复用句柄。在网关下一次从池里取出这个连接去发请求时,发现对端已经 RST,于是拿到了一个中断的连接,表现为 502。

这里的关键是"长连接 + 连接池复用"这个组合。短连接请求不会触发这个问题,因为每次都是新建连接,新连接会正常收到 RST 并且网关可以重试或直接报错。而复用连接时,失败发生在"发送之后、读取响应之前",此时网关已经无法判断请求是否被后端处理过,只能直接返回 502。

我们的处理方式是两层:一是在后端服务的优雅退出里加长一点时间,让在途请求先回完再退出;二是检查网关侧是否开启了 502 的自动重试以及重试的安全边界——对于非幂等的接口,自动重试反而会放大问题,所以这一步必须逐个接口评估,不能全局开。

五、灰度回退:怎么把风险窗口压到最小

排障之后我们重做了发布流程,核心是三件事。

第一,发布前先做一次配置依赖的静态核对。任何"每次请求都要走一次远程调用"的改动,发布前必须评估下游的可用性和延迟预算,不能等到线上才发现。

第二,把"新版本先接少量流量"这件事真正做起来,而不是只在 CCE 侧改副本数。APIG 支持对后端服务配置权重,我们现在按 1% → 10% → 50% → 100% 的节奏推进,每一档停留至少 15 分钟,并且每一档都对比 P99 和 5xx 率再决定是否继续。这样即便再出现类似问题,受影响的面也只有 1%。

第三,回退要能被快速执行。之前回退需要改配置、等生效,紧张的时候几分钟就过去了。现在我们把"降权重回旧版本"和"直接下线新版本实例"两个动作都做成了可以在控制台一键完成的操作,并且提前确认了旧版本镜像还在、且旧版本对配置数据的兼容性不会因为新版本写入的数据格式而失效。

六、几条可以带走的结论

这次排查花了差不多一天半,留下的经验主要有四点。

第一,不要把网关错误码当成后端健康度的直接指标。504 说明慢,502 说明连接断了,它们的根因可以完全不同,混在一起看只会把排查带偏。

第二,任何"每次请求都做一次远程调用"的代码改动,都是一次隐性的级联依赖引入。它平时完全看不出来,往往是在别的服务恰好也在变更的窗口里被放大。这次它是我们自己的升级和内部服务的升级撞在一起才暴露的。

第三,优雅退出的价值在长连接场景下会被放大。短连接时代,Pod 随便重启影响很小;长连接时代,退出瞬间会造成一批 502。这是架构演进带来的运维要求,不是可以忽略的细节。

第四,发布策略的核心不是"多快上线",而是"多快能发现不对、多快能退回去"。我们后来的判断标准是:如果一次发布没有配套的灰度档位和回退预案,那它就不该上线。

最后补一句,如果你们的网关后端也是长连接并且有连接池复用,那么在每次后端服务升级时,都值得提前检查一下优雅退出和连接池复用的组合,这大概率是你们迟早会遇到的同一个坑。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。