DNS优先查询ipv6地址导致curl延时
起因
昨天有大活动,服务器进行扩容,跑的新封装的docker镜像,系统ubuntu14,发现用curl调用微信支付接口出现延时。能正确返回结果,但一般有三秒以上的延时。由于线上服务在跑,没有机会详细调试,于是先忽略之。
复现
今天在本地复现,一个简单的tcp连接,没有其他业务操作,时间花了3秒+,肯定哪里出了问题:
1和2之间花了4秒,代码只有golang的dial函数,测试完整代码如下:
package main
import (
"net"
"fmt"
"log"
)
func main() {
log.Println(1);
conn,err:=net.Dial("tcp","api.mch.weixin.qq.com:443")
log.Println(2);
if err!=nil {
fmt.Printf("error: %v",err);
}
log.Println(3);
conn.Write([]byte("hello"));
log.Printf("remote ip: %s",conn.RemoteAddr().String())
log.Println(4);
}
反馈给微信技术
联系到昨天在阿里云的服务器上的现象,怀疑是不是微信支付服务器出现网络问题,于是发封邮件反馈之,不料马上被呛了回来,我只能说:从来没有见过如此理直气壮让我滚回去查代码的客服:
相比而言阿里的同学还是好多了,发工单基本能回,不是他们问题也能帮忙协助分析,给些建议。
继续分析
对这样的回复我只能表示无语,不过也只能无奈的继续分析,本来准备抓包把结果丢他们糊他们一脸,结果却发现了一些有意思的事情:
先查询A记录,然后被cname然后查询AAAA记录,AAAA记录就是ipv6版本的A记录,结果dns服务器返回了查询失败,几个来回几秒的时间就过去了。然后ipv6地址解析失败,继续解析ipv4的地址,能正常解析,访问了。
所以延时的原因应该就清楚了,curl先去解析ipv6的记录,然后再解析ipv4的记录,这样出现了延时
疑问
为什么同样是ubuntu14,我们其他的服务器没有出现,单单docker里面每次都延时?
答:其他服务器默认开启了nscd,缓存了dns查询记录,不会每次查询,所以对业务的影响就很小了。
如何解决
优先方案是开nscd缓存服务,因为不只是解析ipv6的问题,频繁解析dns有很大的时间开销。
然后换个好点的dns,优先ipv6策略越来越多的被使用,为什么影响还不大,因为即使是dns查询失败也可以很快时间的返回,试验过好几个dns,有的dnsAAAA记录即使没有,但是返回时间很短,阿里的dns就卡了数秒,可能跟dns策略有关系。
修改系统配置可能有用,有搜到/etc/gai.conf,但是试验是没效果的,有兴趣的可以研究下。参考:https://community.rackspace.com/products/f/25/t/5110
最次是写host文件,紧急情况下可以用,但一定只能作为临时救急手段。