上一節,我帶你一塊兒學習了網絡性能的評估方法。簡單回顧一下,Linux 網絡基於 TCP/IP協議棧構建,而在協議棧的不一樣層,咱們所關注的網絡性能也不盡相同。git
在應用層,咱們關注的是應用程序的併發鏈接數、每秒請求數、處理延遲、錯誤數等,可使用 wrk、Jmeter 等工具,模擬用戶的負載,獲得想要的測試結果。github
而在傳輸層,咱們關注的是 TCP、UDP 等傳輸層協議的工做情況,好比 TCP 鏈接數、TCP 重傳、TCP 錯誤數等。此時,你可使用 iperf、netperf 等,來測試 TCP 或 UDP的性能。docker
再向下到網絡層,咱們關注的則是網絡包的處理能力,即 PPS。Linux 內核自帶的pktgen,就能夠幫你測試這個指標。ubuntu
因爲低層協議是高層協議的基礎,因此通常狀況下,咱們所說的網絡優化,實際上包含了整個網絡協議棧的全部層的優化。固然,性能要求不一樣,具體須要優化的位置和目標並不
徹底相同。後端
前面在評估網絡性能(好比 HTTP 性能)時,咱們在測試工具中指定了網絡服務的 IP 地址。IP 地址是 TCP/IP 協議中,用來肯定通訊雙方的一個重要標識。每一個 IP 地址又包括了
主機號和網絡號兩部分。相同網絡號的主機組成一個子網;不一樣子網再經過路由器鏈接,組成一個龐大的網絡。瀏覽器
然而,IP 地址雖然方便了機器的通訊,卻給訪問這些服務的人們,帶來了很重的記憶負擔。我相信,沒幾我的能記得住 Github 所在的 IP 地址,由於這串字符,對人腦來講並沒
有什麼含義,不符合咱們的記憶邏輯。緩存
不過,這並不妨礙咱們常用這個服務。爲何呢?固然是由於還有更簡單、方便的方式。咱們能夠經過域名 github.com 訪問,而不是必須依靠具體的 IP 地址,這其實正是域
名系統 DNS 的由來。安全
DNS(Domain Name System),即域名系統,是互聯網中最基礎的一項服務,主要提供域名和 IP 地址之間映射關係的查詢服務。bash
DNS 不只方便了人們訪問不一樣的互聯網服務,更爲不少應用提供了,動態服務發現和全局負載均衡(Global Server Load Balance,GSLB)的機制。這樣,DNS 就能夠選擇離用
戶最近的 IP 來提供服務。即便後端服務的 IP 地址發生變化,用戶依然能夠用相同域名來訪問。服務器
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
實際測試命令以下:
[root@69 ~]# cat /etc/resolv.conf ; generated by /sbin/dhclient-script nameserver 218.30.19.40 nameserver 61.134.1.4
另外,DNS 服務經過資源記錄的方式,來管理全部數據,它支持 A、CNAME、MX、NS、PTR 等多種類型的記錄。好比:
A 記錄,用來把域名轉換成 IP 地址; CNAME 記錄,用來建立別名; 而 NS 記錄,則表示該域名對應的域名服務器地址
簡單來講,當咱們訪問某個網址時,就須要經過 DNS 的 A 記錄,查詢該域名對應的 IP 地址,而後再經過該 IP 來訪問 Web 服務。
好比,仍是以極客時間的網站 time.geekbang.org 爲例,執行下面的 nslookup 命令,就能夠查詢到這個域名的 A 記錄,能夠看到,它的 IP 地址是 39.106.233.176:
nslookup time.geekbang.org # 域名服務器及端口信息 Server: 114.114.114.114 Address: 114.114.114.114#53 # 非權威查詢結果 Non-authoritative answer: Name: time.geekbang.org Address: 39.106.233.17
實際測試命令以下:
[root@69 ~]# nslookup time.geekbang.org Server: 218.30.19.40 Address: 218.30.19.40#53 Non-authoritative answer: Name: time.geekbang.org Address: 39.106.233.176
這裏要注意,因爲 114.114.114.114 並非直接管理 time.geekbang.org 的域名服務器,因此查詢結果是非權威的。使用上面的命令,你只能獲得 114.114.114.114 查詢的結果。
前面還提到了,若是沒有命中緩存,DNS 查詢其實是一個遞歸過程,那有沒有方法能夠知道整個遞歸查詢的執行呢?
其實除了 nslookup,另一個經常使用的 DNS 解析工具 dig ,就提供了 trace 功能,能夠展現遞歸查詢的整個過程。好比你能夠執行下面的命令,獲得查詢結果:
# +trace 表示開啓跟蹤查詢 # +nodnssec 表示禁止 DNS 安全擴展 $ dig +trace +nodnssec time.geekbang.org ; <<>> DiG 9.11.3-1ubuntu1.3-Ubuntu <<>> +trace +nodnssec time.geekbang.org ;; global options: +cmd . 322086 IN NS m.root-servers.net. . 322086 IN NS a.root-servers.net. . 322086 IN NS i.root-servers.net. . 322086 IN NS d.root-servers.net. . 322086 IN NS g.root-servers.net. . 322086 IN NS l.root-servers.net. . 322086 IN NS c.root-servers.net. . 322086 IN NS b.root-servers.net. . 322086 IN NS h.root-servers.net. . 322086 IN NS e.root-servers.net. . 322086 IN NS k.root-servers.net. . 322086 IN NS j.root-servers.net. . 322086 IN NS f.root-servers.net. ;; Received 239 bytes from 114.114.114.114#53(114.114.114.114) in 1340 ms org. 172800 IN NS a0.org.afilias-nst.info. org. 172800 IN NS a2.org.afilias-nst.info. org. 172800 IN NS b0.org.afilias-nst.org. org. 172800 IN NS b2.org.afilias-nst.org. org. 172800 IN NS c0.org.afilias-nst.info. org. 172800 IN NS d0.org.afilias-nst.org. ;; Received 448 bytes from 198.97.190.53#53(h.root-servers.net) in 708 ms geekbang.org. 86400 IN NS dns9.hichina.com. geekbang.org. 86400 IN NS dns10.hichina.com. ;; Received 96 bytes from 199.19.54.1#53(b0.org.afilias-nst.org) in 1833 ms time.geekbang.org. 600 IN A 39.106.233.176 ;; Received 62 bytes from 140.205.41.16#53(dns10.hichina.com) in 4 ms
實際測試命令以下:
[root@69 ~]# dig +trace +nodnssec time.geekbang.org ; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.68.rc1.el6_10.3 <<>> +trace +nodnssec time.geekbang.org ;; global options: +cmd . 794 IN NS h.root-servers.net. . 794 IN NS k.root-servers.net. . 794 IN NS m.root-servers.net. . 794 IN NS d.root-servers.net. . 794 IN NS b.root-servers.net. . 794 IN NS j.root-servers.net. . 794 IN NS l.root-servers.net. . 794 IN NS g.root-servers.net. . 794 IN NS e.root-servers.net. . 794 IN NS f.root-servers.net. . 794 IN NS c.root-servers.net. . 794 IN NS a.root-servers.net. . 794 IN NS i.root-servers.net. ;; Received 228 bytes from 218.30.19.40#53(218.30.19.40) in 52 ms org. 172800 IN NS a0.org.afilias-nst.info. org. 172800 IN NS a2.org.afilias-nst.info. org. 172800 IN NS b0.org.afilias-nst.org. org. 172800 IN NS b2.org.afilias-nst.org. org. 172800 IN NS c0.org.afilias-nst.info. org. 172800 IN NS d0.org.afilias-nst.org. ;; Received 437 bytes from 199.7.83.42#53(199.7.83.42) in 254 ms geekbang.org. 86400 IN NS dns9.hichina.com. geekbang.org. 86400 IN NS dns10.hichina.com. ;; Received 85 bytes from 199.249.120.1#53(199.249.120.1) in 117 ms time.geekbang.org. 600 IN A 39.106.233.176 ;; Received 51 bytes from 140.205.81.16#53(140.205.81.16) in 26 ms
dig trace 的輸出,主要包括四部分。
第一部分,是從 114.114.114.114 查到的一些根域名服務器(.)的 NS 記錄。 第二部分,是從 NS 記錄結果中選一個(h.root-servers.net),並查詢頂級域名 org.的 NS 記錄。 第三部分,是從 org. 的 NS 記錄中選擇一個(b0.org.afilias-nst.org),並查詢二級域名 geekbang.org. 的 NS 服務器。 最後一部分,就是從 geekbang.org. 的 NS 服務器(dns10.hichina.com)查詢最終主機 time.geekbang.org. 的 A 記錄
這個輸出裏展現的各級域名的 NS 記錄,其實就是各級域名服務器的地址,可讓你更清楚 DNS 解析的過程。 爲了幫你更直觀理解遞歸查詢,我把這個過程整理成了一張流程
圖,你能夠保存下來理解。
固然,不只僅是發佈到互聯網的服務須要域名,不少時候,咱們也但願能對局域網內部的主機進行域名解析(即內網域名,大多數狀況下爲主機名)。Linux 也支持這種行爲。
因此,你能夠把主機名和 IP 地址的映射關係,寫入本機的 /etc/hosts 文件中。這樣,指定的主機名就能夠在本地直接找到目標 IP。好比,你能夠執行下面的命令來操做:
cat /etc/hosts 127.0.0.1 localhost localhost.localdomain ::1 localhost6 localhost6.localdomain6 192.168.0.100 domain.com
或者,你還能夠在內網中,搭建自定義的 DNS 服務器,專門用來解析內網中的域名。而內網 DNS 服務器,通常還會設置一個或多個上游 DNS 服務器,用來解析外網的域名。
清楚域名與 DNS 解析的基本原理後,接下來,我就帶你一塊兒來看幾個案例,實戰分析DNS 解析出現問題時,該如何定位。
本次案例仍是基於 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
實際測試命令以下:
[root@69 ~]# cat /etc/resolv.conf ; generated by /sbin/dhclient-script nameserver 218.30.19.40 nameserver 61.134.1.4
能夠看到,我這臺主機配置的 DNS 服務器是 114.114.114.114。
到這裏,準備工做就完成了。接下來,咱們正式進入操做環節。
首先,執行下面的命令,進入今天的第一個案例。若是一切正常,你將能夠看到下面這個輸出:
# 進入案例環境的 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 和 noservers 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#53 Non-authoritative answer: Name: time.geekbang.org Address: 39.106.233.176
到這裏,第一個案例就輕鬆解決了。最後,在終端中執行 exit 命令退出容器,Docker 就會自動清理剛纔運行的容器。
root@luoahong:~# docker pull feisky/dnsutils Using default tag: latest latest: Pulling from feisky/dnsutils 38e2e6cd5626: Pull complete 705054bc3f5b: Pull complete c7051e069564: Pull complete 7308e914506c: Pull complete 9b20820a1a69: Pull complete 8633a2284391: Pull complete 89ab6a8002a6: Pull complete Digest: sha256:a23534daa60aad8736823219852b6dbd9b51e84ddbaf42e38b54c68954719766 Status: Downloaded newer image for feisky/dnsutils:latest root@luoahong:~# docker run -it --rm -v $(mktemp):/etc/resolv.conf feisky/dnsutils bash root@e9ceb1af6733:/# nslookup time.geekbang.org ;; connection timed out; no servers could be reached root@e9ceb1af6733:/# ping -c3 218.30.19.40 PING 218.30.19.40 (218.30.19.40): 56 data bytes 64 bytes from 218.30.19.40: icmp_seq=0 ttl=56 time=4.203 ms 64 bytes from 218.30.19.40: icmp_seq=1 ttl=56 time=2.846 ms 64 bytes from 218.30.19.40: icmp_seq=2 ttl=56 time=2.683 ms --- 218.30.19.40 ping statistics --- 3 packets transmitted, 3 packets received, 0% packet loss round-trip min/avg/max/stddev = 2.683/3.244/4.203/0.681 ms root@e9ceb1af6733:/# cat /etc/resolv.conf root@e9ceb1af6733:/# echo "nameserver 218.30.19.40" > /etc/resolv.conf root@e9ceb1af6733:/# nslookup time.geekbang.org Server: 218.30.19.40 Address: 218.30.19.40#53 Non-authoritative answer: Name: time.geekbang.org Address: 39.106.233.176
接下來,咱們再來看第二個案例。執行下面的命令,啓動一個新的容器,並進入它的終端中:
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#53 Non-authoritative answer: Name: time.geekbang.org Address: 39.106.233.176 real 0m10.349s user 0m0.004s sys 0m0.0
能夠看到,此次解析很是慢,竟然用了 10 秒。若是你屢次運行上面的 nslookup 命令,可能偶爾還會碰到下面這種錯誤:
/# time nslookup time.geekbang.org ;; connection timed out; no servers could be reached real 0m15.011s user 0m0.006s sys 0m0.006s
換句話說,跟上一個案例相似,也會出現解析失敗的狀況。綜合來看,如今 DNS 解析的結果不但比較慢,並且還會發生超時失敗的狀況。
這是爲何呢?碰到這種問題該怎麼處理呢?
其實,根據前面的講解,咱們知道,DNS 解析,說白了就是客戶端與服務器交互的過程,而且這個過程還使用了 UDP 協議。
那麼,對於整個流程來講,解析結果不穩定,就有不少種可能的狀況了。比方說:
DNS 服務器自己有問題,響應慢而且不穩定; 或者是,客戶端到 DNS 服務器的網絡延遲比較大; 再或者,DNS 請求或者響應包,在某些狀況下被鏈路中的網絡設備弄丟了。
根據上面 nslookup 的輸出,你能夠看到,如今客戶端鏈接的 DNS 是 8.8.8.8,這是Google 提供的 DNS 服務。對 Google 咱們仍是比較放心的,DNS 服務器出問題的機率
應該比較小。基本排除了 DNS 服務器的問題,那是否是第二種可能,本機到 DNS 服務器的延遲比較大呢?
前面講過,ping 能夠用來測試服務器的延遲。好比,你能夠運行下面的命令:
/# ping -c3 8.8.8.8 PING 8.8.8.8 (8.8.8.8): 56 data bytes 64 bytes from 8.8.8.8: icmp_seq=0 ttl=31 time=137.637 ms 64 bytes from 8.8.8.8: icmp_seq=1 ttl=31 time=144.743 ms 64 bytes from 8.8.8.8: icmp_seq=2 ttl=31 time=138.576 ms --- 8.8.8.8 ping statistics --- 3 packets transmitted, 3 packets received, 0% packet loss round-trip min/avg/max/stddev = 137.637/140.319/144.743/3.152 ms
從 ping 的輸出能夠看到,這裏的延遲已經達到了 140ms,這也就能夠解釋,爲何解析這麼慢了。實際上,若是你屢次運行上面的 ping 測試,還會看到偶爾出現的丟包現象。
ping -c3 8.8.8.8 PING 8.8.8.8 (8.8.8.8): 56 data bytes 64 bytes from 8.8.8.8: icmp_seq=0 ttl=30 time=134.032 ms 64 bytes from 8.8.8.8: icmp_seq=1 ttl=30 time=431.458 ms --- 8.8.8.8 ping statistics --- 3 packets transmitted, 2 packets received, 33% packet loss round-trip min/avg/max/stddev = 134.032/282.745/431.458/148.713 ms
這也進一步解釋了,爲何 nslookup 偶爾會失敗,正是網絡鏈路中的丟包致使的。碰到這種問題該怎麼辦呢?顯然,既然延遲太大,那就換一個延遲更小的 DNS 服務器,
好比電信提供的 114.114.114.114。
配置以前,咱們能夠先用 ping 測試看看,它的延遲是否是真的比 8.8.8.8 好。執行下面的命令,你就能夠看到,它的延遲只有 31ms:
/# 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=67 time=31.130 ms 64 bytes from 114.114.114.114: icmp_seq=1 ttl=56 time=31.302 ms 64 bytes from 114.114.114.114: icmp_seq=2 ttl=56 time=31.250 ms --- 114.114.114.114 ping statistics --- 3 packets transmitted, 3 packets received, 0% packet loss round-trip min/avg/max/stddev = 31.130/31.227/31.302/0.072 ms
這個結果代表,延遲的確小了不少。咱們繼續執行下面的命令,更換 DNS 服務器,而後,再次執行 nslookup 解析命令:
/# echo nameserver 114.114.114.114 > /etc/resolv.conf /# time nslookup time.geekbang.org Server: 114.114.114.114 Address: 114.114.114.114#53 Non-authoritative answer: Name: time.geekbang.org Address: 39.106.233.176 real 0m0.064s user 0m0.007s sys 0m0.006s
你能夠發現,如今只須要 64ms 就能夠完成解析,比剛纔的 10s 要好不少。
到這裏,問題看似就解決了。不過,若是你屢次運行 nslookup 命令,估計就不是每次都有好結果了。好比,在個人機器中,就常常須要 1s 甚至更多的時間。
/# time nslookup time.geekbang.org Server: 114.114.114.114 Address: 114.114.114.114#53 Non-authoritative answer: Name: time.geekbang.org Address: 39.106.233.176 real 0m1.045s user 0m0.007s sys 0m0.004s
1s 的 DNS 解析時間仍是太長了,對不少應用來講也是不可接受的。那麼,該怎麼解決這個問題呢?我想你必定已經想到了,那就是使用 DNS 緩存。這樣,只有第一次查詢時需
要去 DNS 服務器請求,之後的查詢,只要 DNS 記錄不過時,使用緩存中的記錄就能夠了。
不過要注意,咱們使用的主流 Linux 發行版,除了最新版本的 Ubuntu (如 18.04 或者更新版本)外,其餘版本並無自動配置 DNS 緩存。
因此,想要爲系統開啓 DNS 緩存,就須要你作額外的配置。好比,最簡單的方法,就是使用 dnsmasq。
dnsmasq 是最經常使用的 DNS 緩存服務之一,還常常做爲 DHCP 服務來使用。它的安裝和配置都比較簡單,性能也能夠知足絕大多數應用程序對 DNS 緩存的需求。
咱們繼續在剛纔的容器終端中,執行下面的命令,就能夠啓動 dnsmasq:
/# /etc/init.d/dnsmasq start * Starting DNS forwarder and DHCP server dnsmasq [ OK ]
而後,修改 /etc/resolv.conf,將 DNS 服務器改成 dnsmasq 的監聽地址,這兒是127.0.0.1。接着,從新執行屢次 nslookup 命令:
/# echo nameserver 127.0.0.1 > /etc/resolv.conf /# time nslookup time.geekbang.org Server: 127.0.0.1 Address: 127.0.0.1#53 Non-authoritative answer: Name: time.geekbang.org Address: 39.106.233.176 real 0m0.492s user 0m0.007s sys 0m0.006s /# time nslookup time.geekbang.org Server: 127.0.0.1 Address: 127.0.0.1#53 Non-authoritative answer: Name: time.geekbang.org Address: 39.106.233.176 real 0m0.011s user 0m0.008s sys 0m0.003s
如今咱們能夠看到,只有第一次的解析很慢,須要 0.5s,之後的每次解析都很快,只須要11ms。而且,後面每次 DNS 解析須要的時間也都很穩定。
案例的最後,仍是別忘了執行 exit,退出容器終端,Docker 會自動清理案例容器。
root@luoahong:~# docker run -it --rm --cap-add=NET_ADMIN --dns 8.8.8.8 feisky/dnsutils bash root@8131109d361c:/# time nslookup time.geekbang.org Server: 8.8.8.8 Address: 8.8.8.8#53 Non-authoritative answer: Name: time.geekbang.org Address: 39.106.233.176 real 0m0.217s user 0m0.008s sys 0m0.008s root@8131109d361c:/# time nslookup time.geekbang.org Server: 8.8.8.8 Address: 8.8.8.8#53 Non-authoritative answer: Name: time.geekbang.org Address: 39.106.233.176 real 0m0.199s user 0m0.000s sys 0m0.015s root@8131109d361c:/# time nslookup time.geekbang.org Server: 8.8.8.8 Address: 8.8.8.8#53 Non-authoritative answer: Name: time.geekbang.org Address: 39.106.233.176 real 0m0.156s user 0m0.010s sys 0m0.014s root@8131109d361c:/# ping -c3 8.8.8.8 PING 8.8.8.8 (8.8.8.8): 56 data bytes 64 bytes from 8.8.8.8: icmp_seq=0 ttl=49 time=52.674 ms 64 bytes from 8.8.8.8: icmp_seq=1 ttl=49 time=52.476 ms 64 bytes from 8.8.8.8: icmp_seq=2 ttl=49 time=57.927 ms --- 8.8.8.8 ping statistics --- 3 packets transmitted, 3 packets received, 0% packet loss round-trip min/avg/max/stddev = 52.476/54.359/57.927/2.524 ms root@8131109d361c:/# ping -c3 8.8.8.8 PING 8.8.8.8 (8.8.8.8): 56 data bytes 64 bytes from 8.8.8.8: icmp_seq=0 ttl=49 time=52.268 ms 64 bytes from 8.8.8.8: icmp_seq=1 ttl=49 time=52.333 ms 64 bytes from 8.8.8.8: icmp_seq=2 ttl=49 time=65.540 ms --- 8.8.8.8 ping statistics --- 3 packets transmitted, 3 packets received, 0% packet loss round-trip min/avg/max/stddev = 52.268/56.714/65.540/6.241 ms root@8131109d361c:/# 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=64 time=25.421 ms 64 bytes from 114.114.114.114: icmp_seq=1 ttl=84 time=25.312 ms 64 bytes from 114.114.114.114: icmp_seq=2 ttl=67 time=23.852 ms --- 114.114.114.114 ping statistics --- 3 packets transmitted, 3 packets received, 0% packet loss round-trip min/avg/max/stddev = 23.852/24.862/25.421/0.715 ms root@8131109d361c:/# echo nameserver 114.114.114.114 > /etc/resolv.conf root@8131109d361c:/# time nslookup time.geekbang.org Server: 114.114.114.114 Address: 114.114.114.114#53 Non-authoritative answer: Name: time.geekbang.org Address: 39.106.233.176 real 0m0.076s user 0m0.003s sys 0m0.016s root@8131109d361c:/# time nslookup time.geekbang.org Server: 114.114.114.114 Address: 114.114.114.114#53 Non-authoritative answer: Name: time.geekbang.org Address: 39.106.233.176 real 0m0.063s user 0m0.008s sys 0m0.008s root@8131109d361c:/# /etc/init.d/dnsmasq start * Starting DNS forwarder and DHCP server dnsmasq [ OK ] root@8131109d361c:/# echo nameserver 127.0.0.1 > /etc/resolv.conf root@8131109d361c:/# time nslookup time.geekbang.org Server: 127.0.0.1 Address: 127.0.0.1#53 Non-authoritative answer: Name: time.geekbang.org Address: 39.106.233.176 real 0m0.266s user 0m0.004s sys 0m0.017s root@8131109d361c:/# time nslookup time.geekbang.org Server: 127.0.0.1 Address: 127.0.0.1#53 Non-authoritative answer: Name: time.geekbang.org Address: 39.106.233.176 real 0m0.017s user 0m0.004s sys 0m0.009s root@8131109d361c:/# time nslookup time.geekbang.org Server: 127.0.0.1 Address: 127.0.0.1#53 Non-authoritative answer: Name: time.geekbang.org Address: 39.106.233.176 real 0m0.019s user 0m0.008s sys 0m0.008s
今天,我帶你一塊兒學習了 DNS 的基本原理,並經過幾個案例,帶你一塊兒掌握了,發現DNS 解析問題時的分析和解決思路。
DNS 是互聯網中最基礎的一項服務,提供了域名和 IP 地址間映射關係的查詢服務。不少應用程序在最初開發時,並沒考慮 DNS 解析的問題,後續出現問題後,排查好幾天才能
發現,實際上是 DNS 解析慢致使的。
試想,假如一個 Web 服務的接kou ,每次都須要 1s 時間來等待 DNS 解析,那麼,不管你怎麼優化應用程序的內在邏輯,對用戶來講,這個接口的響應都太慢,由於響應時間老是
會大於 1 秒的。
因此,在應用程序的開發過程當中,咱們必須考慮到 DNS 解析可能帶來的性能問題,掌握常見的優化方法。這裏,我總結了幾種常見的 DNS 優化方法。