XX发送接口超时问题排查
一句话总结
XX发送接口逻辑中调用了YY的http接口,在http client中dns解析没有超时控制,导致http调用偶发超时。
现象
XX上线后,发现线上监控显示发送消息的接口响应时间会有偶发的高峰,查看日志,超时的响应时间多为3-5s,并且在同一时间点出现,最高有9s的超时时间,一台机器每天约有10次左右慢请求(单机send接口qps约1)。
排查
1. 通过业务代码中的分步耗时日志,定位到超时原因是调用反垃圾接口的http请求慢。
2. 查看http client配置,cotimeout为100ms,sotimeout为100ms,远低于5s。
3. 查看http client源代码,http client的超时配置没有问题。
4. 在一台机器上打开http client的debug日志,观察超时时的日志,出问题的请求都打印了
5.
[DEBUG] HttpConnection Open connection to safe.i.t.sina.com.cn:80
日志位置在HttpConnection.java:692
6. 进一步查看代码,发现在socket建连前,解析dns的函数没有传入超时时间:
7.
ReflectionSocketFactory:124
8.
Object remoteaddr = INETSOCKETADDRESS_CONSTRUCTOR.newInstance(
9.
new Object[] { InetAddress.getByName(host), new Integer(port)});
10. 进一步追查代码,最后会走到Inet6AddressImpl.lookupAllHostAddr(Stringhostname),对应实现是native的
11.
jdk/src/solaris/native/java/net/Inet6AddressImpl.c:139
12.
JNIEXPORT jobjectArray JNICALLJava_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
13.
jstring host) {
14.
....
15.
error = (*getaddrinfo_ptr)(hostname, NULL, &hints, &res);
16.
....
17.
}
18.
19.
net_util_md.c:392
20.
getaddrinfo_ptr = (getaddrinfo_f)
21.
JVM_FindLibraryEntry(RTLD_DEFAULT, "getaddrinfo");
22. getaddrinfo的超时时间由操作系统决定,默认5s,重试2次。
23.
$man resolv.conf
24.
...
25.
timeout:n
26.
sets the amount of time the resolver will wait for a response from a remote name server before retrying the query via a different name server. Measured in seconds, the default is RES_TIMEOUT (currently 5, see <resolv.h>). The maximum value for this option is silently capped to 30.
27.
28.
attempts:n
29.
sets the number of times the resolver will send a query to its name servers before giving up and returning an error to the calling application. The default is RES_DFLRETRY (currently 2, see <resolv.h>). The maximum value for this option is silently capped to 5.
30. 查看XX机器线上配置,dns配置为远程服务器,没有修改超时时间,并且配置的dns服务器各不相同,对比发现,使用172网段dns的机器超时请求略多一些。
31. 灰度了一台机器,修改hosts指定dns后,没有再出现超时请求。
解决
1. 使用dnsmasq本地缓存dns。
2. 修改/etc/resolv.conf,调整dns解析最大超时时间。
3. 业务方使用Feature方式调用http接口。
4. http client4.x似乎有非native dns的实现方式,可以控制超时时间(当前client版本为3.x)。