故障定位系列 -2- 服务 & 接口双粒度动态拓扑,精准定位共享连接池故障

上一期,我们分享了 Web 应用接口级的故障定位方法,通过细化到接口级的定位方法,可以精准地过滤掉干扰因素。然而这种方法并不适用所有场景,过于细致的过滤有时会产生新的问题。
本文将以共享连接池故障场景为例进行说明,提出一种利用服务 &接口双粒度动态拓扑进行故障定位的方法。
1 故障背景

链路 1:service-b 的 callB 接口 -> service-p 的 callB 接口 -> service-h 的 callB 接口
链路 2:service-o 的 callO 接口 -> service-p 的 callO 接口 -> service-l 的 callO 接口
其中链路 1 中的 service-p 的 callB 接口和链路 2 中的 callO 接口,共用了同一个 Http 连接池来访问下游不同的服务。
但是尽管如此,两条链路在接口级别上是没有交集的,如下图所示。

在这样的场景下,假如 service-h 的 callB 接口出现了故障,会有以下情况发生:

service-h 的 callB 接口故障 -> 影响到 service-p 的 callB 接口 -> 影响到 service-b 的 callB 接口
service-p 的 callB 接口长期占用 http 连接 -> 共享 Http 连接池中的连接不够用 -> service-p 的 callO 接口获取不到连接而等待 -> 影响到 service-o 的 callIO 接口
也就是说,尽管两条链路的接口调用没有交集,但是因为在同一个服务节点上共享了连接池的资源,链路 1 中的 service-h 服务出现故障会导致链路 2 中的 service-o 服务也出现故障。
此时,假如我们依照接口级根因定位的方法去分析链路 2,就只能只能定位到 service-p 服务的 callO 接口。而真实情况是,链路 1 和链路 2 的故障根因都在 service-h 的 callB 接口。
既然接口级别的根因定位在这里无法准确定位,那应该怎么办?
答案:服务级拓扑和接口级拓扑动态结合。当接口级拓扑无法继续往下分析时,结合服务级拓扑找到答案。
下面案例中将给出具体方案。
2 实战案例
我们到RootTalk Sandbox上进行上述故障场景的复现。
RootTalk Sandbox是一个故障演练和定位的系统,可以进行多种故障场景的复现,目前开放注册。
地址:https://sandbox.databuff.com/
2.1 故障注入

如上图所示进行操作,对拓扑图中的 service-h::k8s 这个服务的所有实例的 CallDB 接口注入耗时突增的故障。
注入后等待 2~3 分钟,可直接点击跳转到 Databuff 的故障定位平台。
2.2 故障定位
登录 Databuff 后可以看到完整故障树,如下图。

点击故障树底部节点,可以定位到接口。

从上面两张图中可以看到,入口服务 service-b 和 service-o 均出现告警,而根因节点都指向 service-h 服务,故障根因是 service-h 的 callB 接口的存在响应时间升高的问题。
我们再来详细看下对 service-p 服务的分析结论:

service-p 的 callB 接口和 callO 接口都出现了问题,是因为 apache-httpclient_2 这个共享连接池导致的相互影响。
点击页面中的链接继续下钻,可以来验证这一结论。
针对 callB 接口来说,客户端和服务端的平均响应时间均发生突变,一般是服务端的问题。

再看 callO 接口,客户端响应时间均发生突变,而服务端没有变化,这种情况可能是客户端或者网络的问题。

继续看 callO 接口的获取连接时间,发现耗时突增,说明连接池中的连接一直在被占用而被迫等待。

综上,我们可以得到明确的根因分析结论:
链路 1 和链路 2 的入口服务 service-b 和 service-o 均出现告警,故障根因是 service-h::k8s 服务中的 callB 接口存在耗时突增;
中间节点 service-p 服务上的 callB 接口和 callO 接口都出现了问题,原因是共享连接池 apache-httpclient_2 一直被占用而被迫等待。
这个结论和前面分析的场景以及注入的故障是匹配的。
评论