Slow-DNS-Lookup問題:默認啟用了 ipv6-dns-lookup 以至於必須等待超時


@鄭昀匯總

 

一. 現象:
Java HttpClient 從主站機房發起對××××的 open.×××.com 域名下 WebService 接口的 HTTP 請求,極其緩慢。
經排查:
1.1. wget 實測結果
指定 IP協議,wget 訪問它的接口,時間為 4.163 秒,基本浪費在解析主機的過程上。
如指定 wget 的 IP協議為IPV4,wget 測試則僅需 0.096 秒。
1.2. wget 對比測試:
指定IP協議,wget 訪問另一個電商的接口,時間為 0.798 秒。
1.3. dig 解析 open.×××.com
發現在解析 open.×××.com 的時候,會 CNAME 到一個全局變量中,再由這個全局變量選擇最優的線路提供訪問。
 
二. 有可能導致 Slow-DNS-Resolution 的原因:
1) 瀏覽器對××××的接口瀏覽快,不能證明什么。譬如火狐默認禁用了 ipv6 dns lookup:
http://images.cnblogs.com/cnblogs_com/zhengyun_ustc/255879/o_clipboard91.png
 
2)Ubuntu 從 10.4 開始引入一個問題:操作系統默認啟用了 ipv6,導致一些應用程序發出 HTTP 請求時,在 ipv4 介入之前,總是先等待 ipv6 DNS lookup 超時(常有人報告需約30秒),這也是一個 DNS lookup 過程緩慢的常見原因。
 
3)也有人報告:『某一天運維部宣告公司網絡已經全部 enable IPv6 了,在此之后在使用 php 的 curl 函數或使用 Linux 下的 wget 訪問一個內部域名時,均發現需要等待大概 5 秒才能得到結果。原因是,沒有為這個域名綁定一個 IPv6 的地址,wget 時必須等 ipv6 DNS lookup 超時。現在很多服務器都開啟了 IPv6 卻沒有路由,無法真正工作,反而導致一些不可預料的問題。』
 
總之,此事應該與 ipv6-dns-lookup 有關。
 
三. 原因:
××××在網絡接入設備上做了調整,解決了問題。
原因:
1)××××使用了 F5 的 GTM 設備(GSLB,全局負載均衡),即我們常說的智能DNS。
2)它把   需要讓不同區域用戶訪問不同IDC節點的域名  通過 F5 的 GTM 來做解析。
3)可能它的設備默認啟用了 ipv6,但對於不同域名卻又沒有配置 ipv6 地址。
 
四. ipv6-dns-lookup 背景知識:
4.1. Java 平台下 ipv6 是如何工作的?
並非所有操作系統都支持 ipv6 協議,即使 Java networking stack 優先嘗試檢測它,並在發現可用時透明地使用它,也還可以利用系統屬性禁用它。在 ipv6 不可用或被顯式禁用的情況下, Inet6Address  對大多數網絡連接操作都不再是有效參數。
引自   javase 的 ipv6 guide  文檔:
第一步, Java networking stack  先確認底層操作系統是否支持 ipv6。如果支持 ipv6 ,Java 將嘗試使用   ipv6 stack
第二步,在 雙堆棧(dual-stack,指ipv4 stack+ipv6 stack)系統上,將創建一個 ipv6 socket。在   separate-stack  系統上,事情要復雜得多,Java 將創建兩個 socket,一個給 ipv4 一個給 ipv6。
第三步,對於客戶端 TCP 應用,一旦 socket 連上了,那   internet-protocol family type  就固定了,多余的那個 socket 就關閉了。對於服務器端 TCP 應用,由於不知道下一個客戶端請求用什么 ip family type,所以這兩個 sockets 將繼續保留。對於 UDP 應用,這兩個 sockets 始終都需要保留。
 
4.2. ipv6 相關的系統參數
系統有兩個參數:
1)首選的 協議棧:ipv4還是ipv6;
2)首選的 地址族(address family type):inet4 還是 inet6。
4.2.1. 協議棧
由於在一個雙堆棧系統上, ipv6 socket 能與 ipv4 和 ipv6 對端交互,所以  ipv6 stack 是默認首選項
你可以通過如下系統參數修改配置:
java.net.preferIPv4Stack=<true|false>
對應的 java 代碼是:
java.lang.System.setProperty("java.net.preferIPv4Stack", "true");
4.2.2. 地址族
默認我們首選 ipv4 地址族。
你可以通過如下系統參數修改配置:
java.net.preferIPv6Addresses=<true|false>
對應的 java 代碼是:
java.lang.System.setProperty("java.net.preferIPv6Addresses", "false");
 
4.3. Linux 上禁用 ipv6 的辦法:

Edit /etc/sysconfig/network. (A reboot will be required)
# vi /etc/sysconfig/network

Change:
NETWORKING_IPV6=yes

To:
NETWORKING_IPV6=no
Disable IPv6 Protocol Stack for Kernel
禁止IPV6的內核模塊

Edit /etc/modprobe.conf.
# vi/etc/modprobe.conf

Add the following 2 lines: (A reboot will be required)
alias net-pf-10 off
alias ipv6 off

 

4.4. F5 上 ipv6 相關設置:
據說,通過如下命令可以設置 BIG-IP 禁用 ipv6 :
bigpipe db Ipv6.Enabled false
bigpipe save all
 
BIG-IP 與 ipv6 有關的參數默認值如下所示:
Ipv6.Enabled = true
Ipv6.Nbr.DelayTime = 1
Ipv6.Nbr.IncompleteTimeout = 5
Ipv6.Nbr.MaxEntries = 2048
Ipv6.Nbr.ReachableTimeout = 30
Ipv6.Nbr.ReapTimeout = 3600
Ipv6.Nbr.Retries = 2
 
附錄A:
-4’‘ --inet4-only’‘ -6’‘ --inet6-only’Force connecting to IPv4 or IPv6 addresses. With ‘ --inet4-only’ or ‘ -4’, Wget will only connect to IPv4 hosts, ignoring AAAA records in DNS, and refusing to connect to IPv6 addresses specified in URLs. Conversely, with ‘ --inet6-only’ or ‘ -6’, Wget will only connect to IPv6 hosts and ignore A records and IPv4 addresses.       
 

參考資源:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM