WEB应用

APISIX运维优化之解决长尾请求(耗时抖动)问题

Jager · 12月12日 · 2021年 · 2184次已读

自从 APISIX 网关推广使用以来,在我们部门已经有很多生产业务接入使用。有一天被拉进了一个问题群,被告知 APISIX 网关性能有问题,整体表现还不如之前的 ZUUL 网关。纳尼?APISIX 性能再怎么不济也不至于比 ZUUL 差吧?

废话少说,直接上手弄了个串行请求对比测试了一下生产环境的 APISIX 网关和 ZUUL 网关,结果大跌眼镜!

正常情况下,APISIX 的耗时都优于 ZUUL 网关,但是 APISIX 偶尔会来一次很高的延迟,如下图所示:

APISIX运维优化之解决长尾请求(耗时抖动)问题
串行延迟测试:NGate 是我们的网关代号,基于 APISIX

很明显,APISIX 偶尔会出现明显大于正常延迟超过 10 倍的超高延迟!

先说下解决办法:

APISIX 开启了 prometheus 插件,在 prometheus 拉取 metric 数据的时候,会消耗 CPU 资源,导致卡顿。因此禁用 APISIX 的 prometheus 插件或停止 prometheus 对 APISIX 数据的周期性拉取,即可解决问题。

以下是官方解释:

简单来说就是,exporter.collect 会消耗大量的 CPU 时间片来计算指标数据,然后新的请求要等待 exporter.collect 计算完了才有机会得到处理。除了 exporter.collect 之外,还有一些类似的操作应该也会导致这个现象,比如 routes 数量很大的情况下增加 route 导致重建 radixtree 等,这一块需要优化。

以下是部分分析过程,感兴趣的可以看看:

把我们自己开发的插件都关闭试了下,发现这个现象依然存在,于是我整理了一个可复现 case 提交到了 APISIX 官方:bug: The latency of request is not stable as expected · Issue #5604 · apache/apisix (github.com)

提交 issue 之后,APISIX 官方非常给力(效率爆赞),院生大佬亲自发邮件让我微信联系(相当亲民),然后当天就拉群沟通了:

APISIX运维优化之解决长尾请求(耗时抖动)问题

第一时间,APISIX 开发同学拿我整理的 case 用例,发现确实有部分延迟不正常:

APISIX运维优化之解决长尾请求(耗时抖动)问题

然后,通过 Nginx 试了下, 发现情况类似:

APISIX运维优化之解决长尾请求(耗时抖动)问题

最终,结论认定在测试用例下未复现异常。然后,我自己也在测试环境对比测试了下,确实和 Nginx 表现接近,没有明显异常情况。但是请求现网就会明显的延迟飙升现象。于是在现网环境也部署了一套 Nginx 代理试了下, 来排除网络问题,发现完全没有任何问题。甚至直接在 APISIX 容器内部发起本地请求也会存在飙升问题,因此和网络应该没关系了。

注:这过程发现一个有意思的现象:虽然延迟飙升,但是 APISIX 的日志记录的 latency 却很低。

再后来几乎就没有什么新的想法了,官方建议装个 openresty-xray 分析下火焰图什么的,结果在腾讯 tlinux 系统里面还挺麻烦,没继续花时间折腾。

注:因篇幅有限,中间更多的折腾过程省略 1 万字...

最后,实在没办法了,凭着最后一点倔强,我在个人腾讯云公有云账号里面参考现网环境复刻了一套 APISIX(弹性集群),结果用 wrk2 测试后 APISIX 直接挂掉了,重启容器才能恢复,我去???

看来,接近真相了。简单分析了下,应该是在公有云里面 APISIX 里面有插件和内网不通,比如自研日志插件和服务发现插件,导致请求堆积了。进而,我试了下禁用日志插件,发现就没问题了。

根据这个提示,灵光一闪,尝试把以下配置全部注释试了下:

plugin_attr:
  prometheus:
    export_uri: /apisix/prometheus/metrics
    enable_export_server: true
    export_addr:
      ip: 0.0.0.0
      port: 9091
  server-info:
    report_interval: 60
    report_ttl: 3600

zhiyan_log:
  env: idc
  topic: default
  proto: udp
  max_batch_number: 500
  max_report_time: 2

discovery:
  eureka:
    host:
      - http://xxxxx
      
    prefix: "/eureka/"
    fetch_interval: 5
    weight: 100
    timeout:
      connect: 2000
      send: 2000
      read: 5000

  polaris:
     cache_size: 1000
     update_time: 3
     max_cache_time: 5

结果,延迟问题消失了?!消失了?!

好吧,这就简单了,把上述插件一项一项放开测试,最终发现是 prometheus 开启后导致延迟抖动,当然只是开启是没问题的,我停止 prometheus 的拉取,卡顿问题也立马消失了:

APISIX运维优化之解决长尾请求(耗时抖动)问题

目前官方已经对prometheus 插件发起了优化讨论:[DISCUSS]: Improving the performance of the prometheus plugin · Issue #5755 · apache/apisix (github.com),我们就只能静待官方的优化版本了,只是这期间,我们的网关就只能先 L 奔了。

0 条回应
  1. 欧乐安 2021-12-23 · 8:43

    遇到棘手问题确实要折腾半天,拿解决方案就好

  2. pingmin 2022-3-2 · 11:33

    博主你好!
    申请互换友情链接!
    建站常识网-http://nIzhIdaole.cn
    同意的话,回复下,谢谢

  3. xs 2022-3-15 · 14:37

    现在怎么样了?

    • avatar
      Jager 2022-3-18 · 14:27

      官方修复了,但是没发布,估计下个LTS版本就可以了。

  4. zhangdc007 2022-4-14 · 12:13

    看来zuul 比想象的好一些,换掉了么,现在部门用的是go 写的fabio,新搭建的,准备用apache shenyu ,到时候也做一下延迟和性能比对看看

    • avatar
      Jager 2022-4-14 · 17:12

      换掉了,zuul社区已经停止维护了

  5. 蒙蒙 2022-6-28 · 11:28

    我看zuul的耗时要比apisix低啊

  6. cupli 2022-12-19 · 17:09

    受教了。
    请问我想在网关上打印response body ,如何做?

    • avatar
      Jager 2023-4-3 · 16:12

      日志插件目前可以开启resp body