「真®全棧之路 - DNS篇」故事從輸入URL開始.....

前言

很久沒寫博客了,我原先的標題是 「從輸入url到頁面加載完成的XXX」?css

但想着,這是別人嚼爛不少次的內容,缺少挑戰性,並且,頁面操做過程當中能優化的地方實在太多了。html

那就乾脆給本身挖個坑吧,好歹也在運維開發部待過一年的時間。前端

本文將嘗試從先後端或運維多個角度,來述說整個站點從解析到操做過程當中的優化。vue

1. 流程回顧

1. URL的輸入到瀏覽器解析的一系列事件

不少大公司面試喜歡問這樣一道面試題,輸入URL到看見頁面發生了什麼?,今天咱們來總結一下。 簡單來講,共有如下幾個過程webpack

  1. 瀏覽器中輸入網址
  2. 域名解析(DNS),找到IP服務器
  3. 發起TCP鏈接,HTTP三次握手,發送請求(Request
  4. 服務器響應HTTP(Response)
  5. 瀏覽器下載資源 html css js images
  6. 瀏覽器解析代碼(若是服務器有gzip壓縮,瀏覽器先解壓)
  7. 瀏覽器渲染呈現給用戶

2. 結合操做頁面到關閉標籤頁

咱們在頁面渲染完成以後執行某些操做:nginx

  • 按鈕重複點擊
  • 滾動操做
  • 條件查詢檢索

姑且將以上都歸爲 ==> 8. 界面操做web

還在步驟3:發起TCP鏈接 前插入:面試

  • 瀏覽器容許的併發請求優化

下面就讓咱們從DNS解析開始...算法

2. DNS解析流程

Chrome瀏覽器爲例:chrome

  1. Chrome瀏覽器 會首先搜索瀏覽器自身的DNS緩存。

    (緩存時間比較短,默認只有1分鐘,且只能容納1000條緩存)

注: chrome://net-internals/#dns來進行查看 Chrome自身的緩存)

  1. 若是瀏覽器自身的緩存裏面沒有找到對應的條目,那麼Chrome會搜索操做系統自身的DNS緩存
  • Windows - 在Windows中查看DNS緩存條目的過程很是簡單。只需打開命令提示符並輸入如下命令:ipconfig /displaydns

  • Mac - 在Mac上查看DNS緩存條目的過程略有不一樣。須要先打開控制檯應用,從左側邊欄選擇設備,而後輸入:any:mdnsresponder進入搜索欄。接下來,打開命令行並輸入如下命令:

    sudo log config --mode "private_data:on"
    sudo killall -INFO mDNSResponder
    複製代碼

    而後,返回控制檯應用程序並查看緩存的DNS記錄列表。例如,下面的屏幕截圖顯示了wx.qlogo.cn的緩存CNAME記錄。

  1. 若是在系統的DNS緩存也沒有找到,那麼嘗試讀取hosts文件。看看這裏面有沒有該域名對應的IP地址,若是有則解析成功。

    • 注:Windows位於C:\Windows\System32\drivers\etc,Mac則是/etc/hosts
    • 這種操做系統級別的域名解析一般會被不懷好意的人利用,經過修改你hosts文件裏的內容把域名解析到他指定的ip地址上,形成所謂的域名劫持,因此將hosts文件設置成了只讀模式,防止被惡意篡改。
  2. 若是在hosts文件中也沒有找到對應的條目,瀏覽器就會發起一個DNS的系統調用,請求本地域名服務器localDNSLDNS)來解析這個域名。

  • 經過UDP協議向DNS的53端口發起請求,這個請求是遞歸的請求,也就是運營商的DNS服務器必 須得提供給咱們該域名的IP地址)
  • 第一次就會請求本地域名服務器(LDNS)來解析這個域名,這臺服務通常在你城市的某個角落,距離不會很遠,而且他的性能很好,通常都會緩存域名解析結果,大概80%的域名解析到這裏都結束了。
  • 若是本地域名解析服務器也沒有該域名的記錄,則開始遞歸+迭代解析

直到這裏,瀏覽器能作的全部DNS解析已完成,接下來的步驟就是和服務器相關了。不想看的能夠忽略。

  1. 若是localDNS仍然沒有命中,就直接到Root Server域名服務器請求解析。
  2. 根域名服務器返回給本地域名服務器一個所查詢的主域名服務器(gTLD Server)地址。gTLD是國際頂級域名服務器,如.com.cn、.org等,全球只有13臺左右。
  3. 本地域名服務器localDNS再向上一步返回的gTLD服務器發送請求。
  4. 接受請求的gTLD服務器查找並返回此域名對應的Name Server域名服務器的地址,這個Name Server一般就是用戶註冊的域名服務器,例如用戶在某個域名服務提供商申請的域名,那麼這個域名解析任務就由這個域名提供商的服務器來完成。
  5. Name Server域名服務器會查詢存儲的域名和IP的映射關係表,在正常狀況下都根據域名獲得目標IP地址,連同一個TTL值返回給DNS Server域名服務器。
  6. 返回該域名對應的IPTTL值,LDNS會緩存這個域名和IP的對應關係,緩存時間由TTL值控制。
  7. 把解析的結果返回給用戶,用戶根據TTL值緩存在本地系統緩存中,域名解析過程結束。

注:在實際的DNS解析過程當中,可能還不止這11步(第1步其實能夠忽略不計。),如Name Server可能有不少級,或者有一個GTM來負載均衡控制,這都有可能會影響域名解析過程。

不想看文字能夠看圖:

3. DNS優化

首先須要明確一點:DNS緩存存在多級緩存,從離瀏覽器的距離排序的話,有如下幾種:

  • 瀏覽器緩存
  • 系統緩存
  • 路由器緩存
  • IPS服務器緩存
  • 根域名服務器緩存
  • 頂級域名服務器緩存
  • 主域名服務器緩存。

若是每次都通過這麼多步驟解析,是否太耗時間?如何減小該過程的步驟呢? 那就須要DNS優化了。而在前端優化中與DNS有關的有兩點:

  • 減小DNS的請求次數
  • DNS預解析

DNS做爲互聯網的基礎協議,其解析的速度彷佛很容易被網站優化人員忽視。如今大多數新瀏覽器已經針對DNS解析進行了優化,典型的一次DNS解析須要耗費20-120毫秒,減小DNS解析時間和次數是個很好的優化方式。這裏就再也不述說,着重談DNS預解析吧。

3.1 前端:DNS prefetch

DNS prefetch是讓具備此屬性的域名不須要用戶點擊連接就在後臺解析,而域名解析和內容載入是串行的網絡操做,因此這個方式能 減小用戶的等待時間,提高用戶體驗 。

默認狀況下瀏覽器會對頁面中和當前域名(正在瀏覽網頁的域名)不在同一個域的域名進行預獲取,而且緩存結果,這就是隱式的 DNS Prefetch

若是想對頁面中沒有出現的域進行預獲取,那麼就要使用顯示的 DNS Prefetch

其用法也很簡單,只要在link標籤上加上對應的屬性:

/* 這是用來告知瀏覽器當前頁面要作DNS預解析 */
<meta http-equiv="x-dns-prefetch-control" content="on" /> 
<link rel="dns-prefetch" href="//example.com">
複製代碼
  • 若是你的頁面中須要大量訪問不一樣域名的資源,能夠利用這項技術加快資源的獲取,從而得到更好的用戶體驗。
  • 須要注意的是,DNS預解析雖好,可是也不能濫用。若是對多頁面重複DNS預解析,會增長DNS的查詢次數。

目前不少大型站點也應用了這一優化,例如:

淘寶:

京東:

若是須要禁止隱式的 DNS Prefetch,可使用如下的標籤:

<meta http-equiv="x-dns-prefetch-control" content="off">
複製代碼

3.2 後端&運維:CDNHTTPDNS

實際上後端&運維能作的優化有三種:

  • CDN
  • HTTPDNS
  • DNS負載均衡

但稍微大型的Web站點,基本捨棄DNS負載均衡這一方案了,缺點太多。感興趣的能夠自行搜索瞭解。

1. CDNDNS循環

CDN, 全稱是Content Delivery Network,即內容分發網絡。其目的是經過在現有的Internet中增長一層新的CACHE(緩存)層,將網站的內容發佈到最接近用戶的網絡」邊緣「的節點,使用戶能夠就近取得所需的內容,提升用戶訪問網站的響應速度。

DNS循環: 當權威DNS發現一個域名映射多個IP時,會使用IP輪詢的方式來將IP平均分配給多個DNS請求,從而達到負載均衡的效果。

爲何須要CDN?

  • 因爲DNS循環時平均分配,不能根據不一樣服務器的負載狀況優化分配,甚至若是有一臺服務器宕機了,DNS不能及時瞭解到該狀況把該服務器的IP分配出去,便會形成沒法訪問。
  • 所以,在權威 DNS 和 服務器之間加上一個CDN層就顯得很必要了。
  • CDN 在具有調度分配服務器能力的基礎上,可以同步服務器運行狀況,而後根據該狀況及時適當調整調度策略,從而使得負載均衡能力大大提升。

CDN好處:

  • 解決服務器端的「第一千米」問題。
  • 緩解甚至消除了不一樣運營商之間互聯的瓶頸形成的影響。
  • 減輕了各省的出口帶寬壓力。
  • 緩解了骨幹網的壓力。
  • 優化了網上熱點內容的分佈。

CDN的訪問步驟:

(1)未部署CDN應用前:

網絡請求路徑:

  • 請求:本機網絡(局域網)——》運營商網絡——》應用服務器機房
  • 響應:應用服務器機房——》運營商網絡——》本機網絡(局域網)

在不考慮複雜網絡的狀況下,從請求到響應須要通過3個節點,6個步驟完成一次用戶訪問操做。

(2)部署CDN應用後:

網絡路徑:

  • 請求:本機網絡(局域網)——》運營商網絡
  • 響應:運營商網絡——》本機網絡(局域網)

在不考慮複雜網絡的狀況下,從請求到響應須要通過2個節點,2個步驟完成一次用戶訪問操做。

與不部署CDN服務相比,減小了1個節點,4個步驟的訪問。極大的提升的系統的響應速度。

如下是結合具體網絡運維的步驟:

step1:用戶向localDNS發起請求查詢輸入域名對應的IP地址(如有緩存直接返回,不然去rootDNS查詢);

step2:localDNS迭代向rootDNS查詢,逐級迭代,rootDNS=>頂級DNS=>權限DNS;

step3:得到權限DNS後,localDNS向權限DNS發起域名解析請求;

step4:權限DNS一般會將域名CNAME
【若是有有CNAME則解析CNAME對應的CDN服務,不然的話默認爲普通請求,直接返回解析到的IP】到另外一個域名,這個域名最終會被指向CDN網絡中的智能DNS負載均衡系統;

step5:DNS負載均衡系統經過一些智能算法,將最合適的CDN節點IP地址返回給localDNS;

step6:localDNS將得到的IP地址返回給用戶;

step7:用戶獲得節點的IP地址後,向該節點發起訪問請求;

step8:CDN節點返回請求文件,若是該節點中請求的文件不存在,就會再回到源站獲取這個文件,而後返回給用戶。
複製代碼

2. HTTPDNS:解決DNS挾持:

來自:也談 HTTPS - HTTPDNS + HTTPS

在慣有的印象中,不少時候以爲站點上完HTTPS協議就VANS。其實否則:

  • 儘管使用了 HTTPS 技術,部分邪惡的運營商,仍然使用DNS污染技術,讓域名指向的他們本身服務器。
  • 而這些服務器並無部署SSL服務(就算部署了,也會觸發 SSL 證書 Common name 不一致報警), 致使 443 端口直接被拒絕。

運營商爲了賺廣告錢、省網間結算是不擇手段的。 他們廣泛使用的劫持手段是經過 ISP提供的 DNS 僞造域名。 那有沒有什麼方法能夠解決 DNS劫持呢?

業界有一套解決這類場景的方案,即 HTTPDNS

HTTPDNS使用HTTP協議進行域名解析,代替現有基於UDP的DNS協議,域名解析請求直接發送到HTTPDNS服務器,從而繞過運營商的Local DNS,可以避免Local DNS形成的域名劫持問題和調度不精準問題。

HTTPDNS 的原理很簡單,將 DNS這種容易被劫持的協議,轉爲使用HTTP協議請求Domain <-> IP 映射。 得到正確IP以後,Client本身組裝HTTP協議,從而避免ISP篡改數據。

騰訊做爲首家提供HttpDNS服務的雲服務商,有兩篇相隔四年發佈的文章,很是詳細的揭示其中技術細節:

未完待續...

下一篇的內容講圍繞HTTP 優化的兩個大方向::

  • 減小請求次數。
  • 減小單次請求所花費的時間。

與其對應的內容有:

  • 瀏覽器容許的併發請求優化,nginx配置/ 域名發散收斂。
  • 資源的壓縮與合併,webpack/Gzip 相關。
  • 還有其它興趣使然的內容...

做者掘金文章總集

須要轉載到公衆號的喊我加下白名單就好了。

公衆號

相關文章
相關標籤/搜索