dns解析超時故障分析
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)。