37 | 案例篇:DNS 解析时快时慢,我该怎么办?
生活随笔
收集整理的這篇文章主要介紹了
37 | 案例篇:DNS 解析时快时慢,我该怎么办?
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
簡單回顧一下,Linux 網絡基于 TCP/IP 協議棧構建,而在協議棧的不同層,我們所關注的網絡性能也不盡相同。 在應用層,我們關注的是應用程序的并發連接數、每秒請求數、處理延遲、錯誤數等,可以使用 wrk、JMeter 等工具,模擬用戶的負載,得到想要的測試結果。 而在傳輸層,我們關注的是 TCP、UDP 等傳輸層協議的工作狀況,比如 TCP 連接數、 TCP 重傳、TCP 錯誤數等。此時,你可以使用 iperf、netperf 等,來測試 TCP 或 UDP 的性能。 再向下到網絡層,我們關注的則是網絡包的處理能力,即 PPS。Linux 內核自帶的 pktgen,就可以幫你測試這個指標。 由于低層協議是高層協議的基礎,所以一般情況下,我們所說的網絡優化,實際上包含了整個網絡協議棧的所有層的優化。當然,性能要求不同,具體需要優化的位置和目標并不完全相同。 前面在評估網絡性能(比如 HTTP 性能)時,我們在測試工具中指定了網絡服務的 IP 地址。IP 地址是 TCP/IP 協議中,用來確定通信雙方的一個重要標識。每個 IP 地址又包括了主機號和網絡號兩部分。相同網絡號的主機組成一個子網;不同子網再通過路由器連接,組成一個龐大的網絡。 然而,IP 地址雖然方便了機器的通信,卻給訪問這些服務的人們,帶來了很重的記憶負擔。我相信,沒幾個人能記得住 GitHub 所在的 IP 地址,因為這串字符,對人腦來說并沒有什么含義,不符合我們的記憶邏輯。 不過,這并不妨礙我們經常使用這個服務。為什么呢?當然是因為還有更簡單、方便的方式。我們可以通過域名 github.com 訪問,而不是必須依靠具體的 IP 地址,這其實正是域名系統 DNS 的由來。
DNS
DNS(Domain Name System),即域名系統,是互聯網中最基礎的一項服務,主要提供域名和 IP 地址之間映射關系的查詢服務。 DNS 不僅方便了人們訪問不同的互聯網服務,更為很多應用提供了,動態服務發現和全局負載均衡(Global Server Load Balance,GSLB)的機制。這樣,DNS 就可以選擇離用戶最近的 IP 來提供服務。即使后端服務的 IP 地址發生變化,用戶依然可以用相同域名來訪問。 DNS 顯然是我們工作中基礎而重要的一個環節。那么,DNS 出現問題時,又該如何分析和排查呢?域名與 DNS 解析
域名我們本身都比較熟悉,由一串用點分割開的字符組成,被用作互聯網中的某一臺或某一組計算機的名稱,目的就是為了方便識別,互聯網中提供各種服務的主機位置。 要注意,域名是全球唯一的,需要通過專門的域名注冊商才可以申請注冊。為了組織全球互聯網中的眾多計算機,域名同樣用點來分開,形成一個分層的結構。而每個被點分割開的字符串,就構成了域名中的一個層級,并且位置越靠后,層級越高。 我們以極客時間的網站 time.geekbang.org 為例,來理解域名的含義。這個字符串中,最后面的 org 是頂級域名,中間的 geekbang 是二級域名,而最左邊的 time 則是三級域名。 如下圖所示,注意點(.)是所有域名的根,也就是說所有域名都以點作為后綴,也可以理解為,在域名解析的過程中,所有域名都以點結束。 通過理解這幾個概念,你可以看出,域名主要是為了方便讓人記住,而 IP 地址是機器間的通信的真正機制。把域名轉換為 IP 地址的服務,也就是我們開頭提到的,域名解析服務(DNS),而對應的服務器就是域名服務器,網絡協議則是 DNS 協議。 這里注意,DNS 協議在 TCP/IP 棧中屬于應用層,不過實際傳輸還是基于 UDP 或者 TCP 協議(UDP 居多) ,并且域名服務器一般監聽在端口 53 上。 既然域名以分層的結構進行管理,相對應的,域名解析其實也是用遞歸的方式(從頂級開始,以此類推),發送給每個層級的域名服務器,直到得到解析結果。 不過不要擔心,遞歸查詢的過程并不需要你親自操作,DNS 服務器會替你完成,你要做的,只是預先配置一個可用的 DNS 服務器就可以了。 當然,我們知道,通常來說,每級 DNS 服務器,都會有最近解析記錄的緩存。當緩存命中時,直接用緩存中的記錄應答就可以了。如果緩存過期或者不存在,才需要用剛剛提到的遞歸方式查詢。 所以,系統管理員在配置 Linux 系統的網絡時,除了需要配置 IP 地址,還需要給它配置 DNS 服務器,這樣它才可以通過域名來訪問外部服務。 比如,我的系統配置的就是 114.114.114.114 這個域名服務器。你可以執行下面的命令,來查詢你的系統配置: $ cat /etc/resolv.conf nameserver 114.114.114.114 另外,DNS 服務通過資源記錄的方式,來管理所有數據,它支持 A、CNAME、MX、NS、PTR 等多種類型的記錄。比如:- A 記錄,用來把域名轉換成 IP 地址;
- CNAME 記錄,用來創建別名;
- 而 NS 記錄,則表示該域名對應的域名服務器地址。
案例準備
本次案例還是基于 Ubuntu 18.04,同樣適用于其他的 Linux 系統。我使用的案例環境如下所示: 機器配置:2 CPU,8GB 內存。 預先安裝 docker 等工具,如 apt install docker.io。 你可以先打開一個終端,SSH 登錄到 Ubuntu 機器中,然后執行下面的命令,拉取案例中使用的 Docker 鏡像: $ docker pull feisky/dnsutils Using default tag: latest ... Status: Downloaded newer image for feisky/dnsutils:latest 然后,運行下面的命令,查看主機當前配置的 DNS 服務器: $ cat /etc/resolv.conf nameserver 114.114.114.114 可以看到,我這臺主機配置的 DNS 服務器是 114.114.114.114。 到這里,準備工作就完成了。接下來,我們正式進入操作環節。案例分析
案例 1:DNS 解析失敗
首先,執行下面的命令,進入今天的第一個案例。如果一切正常,你將可以看到下面這個輸出: # 進入案例環境的 SHELL 終端中 $ docker run -it --rm -v $(mktemp):/etc/resolv.conf feisky/dnsutils bash root@7e9ed6ed4974:/# 注意,這兒 root 后面的 7e9ed6ed4974,是 Docker 生成容器的 ID 前綴,你的環境中很可能是不同的 ID,所以直接忽略這一項就可以了。 注意:下面的代碼段中, /# 開頭的命令都表示在容器內部運行的命令。 接著,繼續在容器終端中,執行 DNS 查詢命令,我們還是查詢 time.geekbang.org 的 IP 地址: /# nslookup time.geekbang.org ;; connection timed out; no servers could be reached 你可以發現,這個命令阻塞很久后,還是失敗了,報了 connection timed out 和 no servers could be reached 錯誤。 看到這里,估計你的第一反應就是網絡不通了,到底是不是這樣呢?我們用 ping 工具檢查試試。執行下面的命令,就可以測試本地到 114.114.114.114 的連通性: /# ping -c3 114.114.114.114 PING 114.114.114.114 (114.114.114.114): 56 data bytes 64 bytes from 114.114.114.114: icmp_seq=0 ttl=56 time=31.116 ms 64 bytes from 114.114.114.114: icmp_seq=1 ttl=60 time=31.245 ms 64 bytes from 114.114.114.114: icmp_seq=2 ttl=68 time=31.128 ms --- 114.114.114.114 ping statistics --- 3 packets transmitted, 3 packets received, 0% packet loss round-trip min/avg/max/stddev = 31.116/31.163/31.245/0.058 ms 這個輸出中,你可以看到網絡是通的。那要怎么知道 nslookup 命令失敗的原因呢?這里其實有很多方法,最簡單的一種,就是開啟 nslookup 的調試輸出,查看查詢過程中的詳細步驟,排查其中是否有異常。 比如,我們可以繼續在容器終端中,執行下面的命令: /# nslookup -debug time.geekbang.org ;; Connection to 127.0.0.1#53(127.0.0.1) for time.geekbang.org failed: connection refused. ;; Connection to ::1#53(::1) for time.geekbang.org failed: address not available. 從這次的輸出可以看到,nslookup 連接環回地址(127.0.0.1 和 ::1)的 53 端口失敗。這里就有問題了,為什么會去連接環回地址,而不是我們的先前看到的 114.114.114.114 呢? 你可能已經想到了癥結所在——有可能是因為容器中沒有配置 DNS 服務器。那我們就執行下面的命令確認一下: /# cat /etc/resolv.conf 果然,這個命令沒有任何輸出,說明容器里的確沒有配置 DNS 服務器。到這一步,很自然的,我們就知道了解決方法。在 /etc/resolv.conf 文件中,配置上 DNS 服務器就可以了。 你可以執行下面的命令,在配置好 DNS 服務器后,重新執行 nslookup 命令。自然,我們現在發現,這次可以正常解析了: /# echo "nameserver 114.114.114.114" > /etc/resolv.conf /# nslookup time.geekbang.org Server: 114.114.114.114 Address: 114.114.114.114#53Non-authoritative answer: Name: time.geekbang.org Address: 39.106.233.176 到這里,第一個案例就輕松解決了。最后,在終端中執行 exit 命令退出容器,Docker 就會自動清理剛才運行的容器。案例 2:DNS 解析不穩定
接下來,我們再來看第二個案例。執行下面的命令,啟動一個新的容器,并進入它的終端中: $ docker run -it --rm --cap-add=NET_ADMIN --dns 8.8.8.8 feisky/dnsutils bash root@0cd3ee0c8ecb:/# 然后,跟上一個案例一樣,還是運行 nslookup 命令,解析 time.geekbang.org 的 IP 地址。不過,這次要加一個 time 命令,輸出解析所用時間。如果一切正常,你可能會看到如下輸出: /# time nslookup time.geekbang.org Server: 8.8.8.8 Address: 8.8.8.8#53Non-authoritative answer: Name: time.geekbang.org Address: 39.106.233.176real 0m10.349s user 0m0.004s sys 0m0.0 可以看到,這次解析非常慢,居然用了 10 秒。如果你多次運行上面的 nslookup 命令,可能偶爾還會碰到下面這種錯誤: /# time nslookup time.geekbang.org ;; connection timed out; no servers could be reachedreal 0m15.011s user 0m0.006s sys 0m0.006s 換句話說,跟上一個案例類似,也會出現解析失敗的情況。綜合來看,現在 DNS 解析的結果不但比較慢,而且還會發生超時失敗的情況。 這是為什么呢?碰到這種問題該怎么處理呢? 其實,根據前面的講解,我們知道,DNS 解析,說白了就是客戶端與服務器交互的過程,并且這個過程還使用了 UDP 協議。 那么,對于整個流程來說,解析結果不穩定,就有很多種可能的情況了。比方說:- DNS 服務器本身有問題,響應慢并且不穩定;
- 或者是,客戶端到 DNS 服務器的網絡延遲比較大;
- 再或者,DNS 請求或者響應包,在某些情況下被鏈路中的網絡設備弄丟了。
小結
今天,我帶你一起學習了 DNS 的基本原理,并通過幾個案例,帶你一起掌握了,發現 DNS 解析問題時的分析和解決思路。 DNS 是互聯網中最基礎的一項服務,提供了域名和 IP 地址間映射關系的查詢服務。很多應用程序在最初開發時,并沒考慮 DNS 解析的問題,后續出現問題后,排查好幾天才能發現,其實是 DNS 解析慢導致的。 試想,假如一個 Web 服務的接口,每次都需要 1s 時間來等待 DNS 解析,那么,無論你怎么優化應用程序的內在邏輯,對用戶來說,這個接口的響應都太慢,因為響應時間總是會大于 1 秒的。 所以,在應用程序的開發過程中,我們必須考慮到 DNS 解析可能帶來的性能問題,掌握常見的優化方法。這里,我總結了幾種常見的 DNS 優化方法。- 對 DNS 解析的結果進行緩存。緩存是最有效的方法,但要注意,一旦緩存過期,還是要去 DNS 服務器重新獲取新記錄。不過,這對大部分應用程序來說都是可接受的。
- 對 DNS 解析的結果進行預取。這是瀏覽器等 Web 應用中最常用的方法,也就是說,不等用戶點擊頁面上的超鏈接,瀏覽器就會在后臺自動解析域名,并把結果緩存起來。
- 使用 HTTPDNS 取代常規的 DNS 解析。這是很多移動應用會選擇的方法,特別是如今域名劫持普遍存在,使用 HTTP 協議繞過鏈路中的 DNS 服務器,就可以避免域名劫持的問題。
- 基于 DNS 的全局負載均衡(GSLB)。這不僅為服務提供了負載均衡和高可用的功能,還可以根據用戶的位置,返回距離最近的 IP 地址。
總結
以上是生活随笔為你收集整理的37 | 案例篇:DNS 解析时快时慢,我该怎么办?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 36 | 套路篇:怎么评估系统的网络性能
- 下一篇: 38 | 案例篇:怎么使用 tcpdum