你的域名是如何變成 IP 地址的?

我的 個人網站 上線了,上面可以更好的檢索歷史文章,並且可以對文章進行留言,歡迎大家訪問

可能大家都知道或者被問過一個問題,那就是很經典的「從瀏覽器輸入 URL 再到頁面展示,都發生了什麼」。這個問題雖然簡單,但是真的能夠從回答的各種細節上看出不同人之間的水平差距。

這篇文章主要是聊一聊輸入 URL 之後的第一步——域名解析

域名就類似於 www.google.com,而通過 ping 命令,就可以查詢到對應域名的 IP 地址了。

那爲什麼又要有域名,又要有 IP 呢?

域名、IP 共存

首先還是解釋一下,爲什麼會出現現在這種域名、IP 地址共存的情況。主要有兩個點:

  1. 提升用戶體驗
  2. 提高運行效率

分別解釋一下,IP 地址長度爲 32 位,平時用十進制來表示的話,就長這樣——192.168.1.0 ,但是想象一下,如果我們要訪問某個網站需要讓我們輸入這麼一長串數字,體驗肯定相當差,首先記憶這麼長串數字對很多人來說就很痛苦,更何況我們常用的網站肯定不止一個。

除此之外,如果你給其他人推廣你的網站,你吧啦吧啦說了一大堆,然後來個「如果你感興趣,請訪問我們的網站 192.168.1.0」,然後就沒有然後了。

這也是爲啥現在仍然在使用域名,方便人腦去記憶。

那爲啥還需要 IP 地址呢?因爲 IPv4 中的 IP 地址只需要 4 個字節,而用字符串表示的域名最少也需要幾十個字節,長的甚至達到幾百字節,而這會大大的增加底層路由器的負擔。

這也是爲啥 IP 地址仍然在被使用。人來使用域名,而路由器層則使用 IP 地址,就跟我們書寫的是我們能認識的字符,而最終計算機認識的是一堆二進制一樣。

DNS 解析

知道了這個背景之後,我們就可以來看看「域名」是如果變成「IP 地址」的。

首先我們知道,會往 DNS 服務器發送請求,那問題就來了,瀏覽器怎麼知道 DNS 服務器的地址是啥?

答案是提前配置好的。當然這不是唯一的方式,DNS 也有可能通過 DHCP(Dynamic Host Configuration Protocol) 動態分配的。

例如,MacOS 中的 DNS 配置就長下面這樣。

當然,你也可以通過命令行來查看、修改,地址在 /etc/resolv.conf

有了 DNS 服務器,那麼你可能會覺得,接下來的事情就很簡單了:

我給你傳個域名,你返給我對應的 IP 地址即可。那問題來了,現在互聯網中有數萬臺的 DNS 服務器,我怎麼知道數據在哪臺服務器上?難道要一臺一臺的遍歷請求這數萬臺服務器嗎?

我相信你肯定沒有感知到在瀏覽器中輸入域名到頁面展示會花費那麼久,這也說明肯定不是一臺一臺服務器進行遍歷的。

域名的組成

要了解 DNS 是如何對其進行優化的,我們需要先知道域名的組成部分。看到這,很可能你會這麼想:

啥組成?不就是一堆字符串嗎?

實際上,域名是有由不同的組成的,每個 . 隔開的部分就是一個

這裏舉個例子,假設我們分析的域名爲 www.google.com ,從我們平時寫快遞的收貨地址的慣性思維來看,這個域的各個部分大小可能是這樣的:

www > google > com

但是實際上並不是這樣,而是:

. > com > google > www

你甚至發現,最大的還是個 . 。其實完整的域名應該是 www.google.com.. 代表根域,因爲根域對於所有的域名來說,意義都一樣,所以平時我們都把最後的點給省略了。

每個域都有自己的專屬名詞:

. > com > google > www

根域 | 一級級域|二級域名|(子域名)|主機名

當然,我們知道還可以針對二級域名再劃分子域名,類似於 mail.google.com

所以看到這,你應該能夠理解域名是由層次的這個概念了,我再舉個比較的通俗的例子。

com 公司的 google 部門的 www。https://mail.google.com/mail/u/0/#inbox

DNS 的分層

瞭解完域名的分層之後,DNS 是如何優化域名解析的問題就迎刃而解了,那就是——分層。

DNS 服務器會將域名的數據分佈式的存儲在各個 DNS 服務器上,但是同一個域的數據,會存儲在同一臺 DNS 服務器上,同一臺 DNS 服務器可以存儲多個域的數據。

這麼說可能會有些抽象,一圖勝千言,其實就是這樣:

有了對數據的分層,那麼查詢數據就會很有節奏感

查詢域名數據

一圖勝千言,有了分層的機制,整個的查詢過程就會長這樣:

首先會去配置的 DNS 服務器中查詢,這個其實一般都是本地或者內網中的 DNS 服務器。如果沒有找到,就會去問根域要,說哥們,我這裏需要 www.google.com 的 IP 地址。

根域一看,我這裏沒有啊,但是我知道 com 域的 DNS 服務器地址,他可能知道。

然後 com 域的 DNS 服務器一看,www.google.com 的 IP 地址我也不知道,但是我知道 google.com 域的 DNS 服務器的地址,他可能知道,你再去問問他。

就這樣一路問下去,最終就能夠找到 www.google.com 所對應的 IP 地址了。

根域名服務器

看了上面的流程,可能你還是會有點疑問。因爲去找 DNS 服務器查詢 IP 地址時,初始的 DNS 的服務器的 IP 地址是走的本地計算機的配置的。那在分層查詢時,我怎麼知道有哪些根服務器?以及我怎麼知道這些根服務器的 IP 地址是啥?

答案是內置

我們的設備,或者說所有能上網的設備都會內置根服務器的列表。總共有 13 臺根 DNS 服務器,分別是[a-m].root-servers.net ,這些根服務器的地址根本不需要查詢就能直接獲取。

當然,稍微想想也知道,13 臺服務器是很難扛住全球互聯網用戶的請求的,實際上對於這 13 臺服務器有很多的鏡像服務器

眼見爲實

說了這麼多虛的概念,接下來我們通過 dig 命令來實際操作一下。

可以看到,在 QUESTION SECTION 下的完整域名是 www.google.com. 是帶了根域的,那後面的這個 INA 又是啥意思呢?

這是因爲,在向 DNS 服務器查詢請求的時候,需要三個參數,分別是:

  1. 域名(例如 www.google.com)
  2. 網絡類型(Class 設計之初,考慮到了多種網絡並存的場景,但是目前實際上只有一種網絡——互聯網,所以該參數的值一直都會爲 —— IN
  3. 類型(例如 A 表示 IP 地址,而 MX 則表示郵件服務器的地址)

而在 ANSWER SECTION 中,則是 DNS 服務的響應結果,上圖中顯示了總有 6 條 DNS 記錄,並且在後面返回了其對應的 IP 地址。

而其中的 69 則是 TTL,單位是秒,代表了在 69 之內都不用再次發送請求了。

最下面則是統計的信息,本次 DNS 查詢所話費的時間,以及請求的 DNS 服務器的地址和端口。這個服務器地址是我們本機配置的 DNS 服務器的地址。

眼尖的可能發現了,上圖中根本沒有設計到對根服務器的請求。這是因爲這個命令把這部分給省略掉了,我們可能通過加上 +trace 命令行參數來查看詳細的分級查詢過程

這次我們以 www.36kr.com 來作爲例子。

可以看到,上圖中列出了所有的根域名服務器,然後去找 com 域要,然後再找 36kr.com 域去要,最終是拿到了 www.36kr.com 的 IP 地址。

緩存機制

當然,如果每次都從根服務器開始往下找,明顯是不合理的,因爲域名和 IP 地址的對應關係本來變動的就不頻繁,所以 DNS 服務器是都會將結果緩存的。

並且,在下圖中:

我只寫了一個 DNS 服務器中有同級別的域信息,但是實際上不同層級的域信息可能存在於同一個 DNS 服務器,舉個例子,com 域和 google.com 域可能在同一臺機器上。

但是,這個緩存是有有效期的。如果在這個有效期內 DNS 數據發生了變化,那麼緩存中的數據就會不正確,此時需要手動的將 DNS 刪除。

本篇文章已放到我的 Github github.com/sh-blog 中,歡迎 Star。微信搜索關注【SH的全棧筆記】,回覆【隊列】獲取MQ學習資料,包含基礎概念解析和RocketMQ詳細的源碼解析,持續更新中。

如果你覺得這篇文章對你有幫助,還麻煩點個贊關個注分個享留個言

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章