第三方服务接口响应慢的深入分析

明星八卦 浏览(1103)

我想要分享的app2019.7.14分享

背景&现象:

内部开发环境OS是centos6.8 x64,请求第三方接口非常慢,并且应用程序报告超时错误。

image.php?url=0Mp4zyKFcs

问题分析和解决方案:

同事使用curl命令确定解析时间很慢。

image.php?url=0Mp4zyIegu

image.php?url=0Mp4zyJEWv

可以稳定地再现上述现象。

curl命令显示问题在于域名解析。在同事将/etc/resolv.conf的名称服务器调整为223.5.5.5后,故障被删除。同事们对自建DNS问题表示严重怀疑。看起来外观就像是自建DNS的问题,但考虑到在大多数情况下问题的根本原因和外观相距甚远,需要仔细安排。首先捕获包:

image.php?url=0Mp4zy7SHo

比较发现,当curl发起http请求时,客户端同时发起ipv4,ipv6解析请求,ipv4,ipv6解析请求快速响应,并且thirdwx.qlogo.cn ipv6解析请求响应非常慢。 ipv6解析请求超时会导致整个解析花费太长时间,并且接口响应很慢。从现象的角度来看,其他公司的AAAA域名解析没有问题,而这个问题存在于thirdwx.qlogo.cn。首先看看3rdwx.qlogo.cn的权限dns的ip,用dig来查看它的A,AAAA和其他类型的记录:

解析响应标志是aa,描述是权威的。根据RFC 1034(第3.6.2节中的描述:

如果节点上存在CNAME RR,则不应存在其他数据;这可以确保规范名称及其别名的数据不能不同。

RFC描述了cname与其他解析记录类型互斥。

Qlogo.cn权威DNS thirdwx.qlogo.cn也存在CNAME,A记录,只能推测qlogo.cn权威DNS自我研究,并不严格遵守RFC1034。这里缓慢的原因很可能与qlogo.cn权威DNS有关。 [至少在开源绑定中,dnsmasq无法实现],观察AAAA的返回结果:

Thirdwx.qlogo.cn CNAME cwx.qlogo.cn。

解析器将继续递归查询cwx.qlogo.cn,继续挖掘AAAA查询cwx.qlogo.cn

直接通过其权威的DNS查询,没有发现任何错误。

向公共DNS发起AAAA解析请求,并观察结果:

通过公共DNS的解析状态是: SERVFAIL。最初的原因是明确的:

绑定缓存/递归DNS ---> Office Area Control DNS ---> 114.114.114.114公共DNS ---->域名的权威DNS。

默认情况下,SERVFAIL状态在bind中没有命中nagetive缓存,但是会有一个大约1s的缓存。域控制的DNS具有相同的行为(它不会缓存SERVFAIL),并且公共DNS缓存SERVFAIL一段时间(每个都)实现略有不同),cwx.qlogo.cn将启动AAAA递归查询每次AAAA决议请求,

绑定--->域控制dns --->公共DNS114.114.114.114 - >权威dns,导致总体响应时间更长,从而影响第三方接口的响应时间。正常的A,AAAA和CNAME响应(状态非SERVFAIL状态)由每个级别的DNS(包括负缓存)缓存,从而避免每个递归解析,因此第三方域名(如:)可以解析快点。

接下来,找到递归查询状态: SERVFAIL的原因。因为bind的递归查询状态和公共DNS递归查询状态都是SERVFAIL,所以可以使用bind来定位(仅使用RFC文档,开源代码进行一瞥)。

关闭本地绑定的转发,启用自递归,启用dbug,并启动cAAA.qlogo.cn AAAA解析。

下载相应版本的源代码,并根据错误日志快速找到代码文件和代码段。

LIB/DNS/resolver.c

此代码更长,并非全部发布。绑定错误位于resolve.c中的no_anwser_response函数中。

RFC2308的响应没有数据描述(同时参见NXDOMAIN以加快对代码逻辑的理解),其中响应没有数据有4种类型,当前故障的响应类型属于类型2(在这种情况下,NS in阅读SOA)。

(第2.2节)

从dig trace,qlogo.cn和cwx.qlogo.cn属于两个不同的授权域(请注意,它不是域名),其中qlogo.cn是父域,cwx.qlogo.cn属于子域,和qlogo.cn授权cwx。qlogo.cn的NS(即胶水记录)是: ns-tel1.qq.com

通过cwx.qlogo.cn的权威DNS: ns-tel1.qq.com查看cwx.qlogo.cn的NS记录。从输出中,子域cwx.qlogo.cn不会添加自己的NS记录。响应权限部分的SOA中的NS地址是父域(ns1.qq.com)的NS地址,这是有问题的。 qlogo.cn的NS是ns1.qq.com,qlogo.cn的子域是cwx.qlogo。cn到ns-tel1.qq.com,然而,子域cwx.qlogo.cn的SOA中的NS仍然指向父域NS(ns1.qq.com),导致递归解析器解析异常(参见RFC1912)第2.8节)。 p>

: qlogo.cn(SOA)不是区域cwx.qlogo.cn的子域。

这导致了SERVFAIL。根据这个过程,cwx.qlogo.cn的A分析可能会有这样的问题,但它不在实际过程中。这是因为权威dns具有A记录,并且A解析请求不会转到no_answer_response的处理逻辑。即使域cwx.qlogo.cn上没有任何类型的记录,也不会导致异常,因为在这种情况下转到NXDOMAIN的处理逻辑,仍然无法获得no_answer_response,以及NXDOMAIN和NXDOMAIN的响应NOERROR状态可以在所有级别由DNS缓存,因此不会导致性能问题。

所以要实现上述场景,至少需要:

cwx.qlogo.cn域上还有其他类型的解析记录[不能有AAAA]

cwx.qlogo.cn的SOA中的NS地址配置错误

父域qlogo.cn将子域cwx.qlogo.cn授权给不同的权威DNS,子域的权威DNS没有自己的NS记录。

由于qlogo.cn的权威DNS是第三家公司自行开发的实现,因此很难窥探具体的实现。因此,开源绑定用作再现,跟踪和定位的示例。

解决方案:

1.(通过绑定的情况)DNS服务器端调整,cwx.qlogo.cn配置NS地址:(如: ns1-tel1.qq.com),或修改cwx.qlogo.cn的SOA中的ns地址对于子域NS:(ns1-tel1.qq.com)。

2.客户端调整相关参数,但只能解除。

1.调整dns客户端的行为,将:添加到/etc/resolv.conf

选项超时: 1次尝试: 1旋转单次请求重新打开

单请求重新开启说明:

(此参数用于A,AAAA解析请求以启动具有不同源端口的解析请求),这可以在某种程度上减慢速度。另一种是调整/etc/resolv.conf中的timeout参数以缩短超时响应并加快AAAA超时以快速失败。

2.禁用系统OS的ipv6只能更改应用层套接字的某些默认参数,但可能无法完全禁止应用程序启动AAAA查询。核心是glibc域名解析函数getaddrinfo的行为在创建套接字时受参数的影响。例如,创建一个套接字地址族(AF_INET只有ipv4,AF_INET6只有ipv6,AF_UNSPEC ipv4/ipv6)glibc默认hints.ai_family是AF_UNSPEC,所以禁用OS的ipv6后没有效果(例如,ssh, telnet使用地址族,os被禁止)Ipv6无效),这块比较复杂,建议不要先ipv6场景禁用ipv6。

3.调整中间dns链接,让中间链接nagetive缓存强制缓存AAAA解析结果,以避免隐遁。

我在github上搜索,发现dnsmasq有一个disable-aaaa补丁。没有现成的解决方案。 Bind具有filter-aaaa-on-v4 yes配置项,但客户端发起的AAAA解析请求仍由AAAA执行。递归,绑定没有解决方案。另外,SERVFAIL的公共DNS缓存时间比绑定的默认值1s长,这可以减轻递归引起的时间开销(这就是为什么在故障开始时名称服务器调整为公共DNS后接口快速响应的原因)。另一种方法是在绑定所在的服务器上启用iptables规则,过滤掉aaaa请求/删除AAAA请求。

收集报告投诉