DNS Prefetching - 預先做DNS解析,幫助網頁載入速度更快

DNS Prefetching - 預先做DNS解析,幫助網頁載入速度更快

DNS Prefetching - 預先做DNS解析,幫助網頁載入速度更快

前陣子看見Addy Osmani大大在Facebook上發表了一張圖片(原文)。

Resource Hints

在研究淘寶SEO策略時有略略看到頁面上出現這樣的設定,但對於網站效能提升這一塊比較陌生的我,並沒有做太多的研究(只知道是做什麼用的),剛好藉這次機會來看看相關資料並做整理。

什麼是DNS Prefetching?

預先做DNS解析(domain name resolution),將人類可理解的domain name,轉為IP address。瀏覽器載入頁面和資源時需做DNS解析,但若等到瀏覽該頁或要下載資源時才做DNS解析就太遲了(使用者需要等待一段時間),因此可預先執行。(關於DNS Lookup流程可參考 DNS 名稱解析程序。)

預先做DNS解析的好處是使用者瀏覽之後的頁面時,可減少DNS Lookup的時間,感覺速度變快了。

如何使用DNS Prefetching?

在HTML的 <head> 加入 <link rel="dns-prefetch" href="https://my-site.com"> 。 使用這個指令後,頁面上 <a> 的連結也都會開啟DNS Prefetching。

附註,DNS Prefetching在https下是無法使用的。若要在https下開啟DNS Prefetching,必須在 <head> 加上 <meta http-equiv="x-dns-prefetch-control" content="on"> 才能啟動DNS Prefetching。但只能啟動連結,而無法啟動手動設定的資源。

順道一提,<link rel="dns-prefetch" href="//host_name_to_prefetch.com"><link rel="dns-prefetch" href="http://host_name_to_prefetch.com"> 意義是相同的,「//」表示網址起始是一個host name。

使用DNS Prefetching的時機

  • 該頁面有許多靜態資源但放在各個不同的domain底下,例如圖檔、CSS檔案、JS檔案等:例如,在這個頁面或這個網站將圖片放在 http://a.img.com.twhttp://b.img.com.tw 這些domain底下。我希望瀏覽該頁面時能先對這兩個domain name做DNS Prefetching,於是可在 <head> 加上

    <link rel="dns-prefetch" href="http://a.img.com.tw">
    <link rel="dns-prefetch" href="http://b.img.com.tw">
    
  • 該頁會轉跳到不同domain下的頁面,因此可在指令先指定對轉跳的domain做DNS Prefetching

適合的對象

  • 電商網站的商品頁大量載入不同domain下的商品圖,例如:淘寶
  • 手機網頁,需要提高頁面載入完成的速度

成效評估

測試範例

拿我們家露天拍賣的測試機商品頁來看看...

尚未做DNS Prefetch之前

DNS Prefetch

做了DNS Prefetch之後

我加了這幾條指令到 <head> 裡面...

<link rel="dns-prefetch" href="http://a.rimg.com.tw">
<link rel="dns-prefetch" href="http://b.rimg.com.tw">
<link rel="dns-prefetch" href="http://c.rimg.com.tw">
<link rel="dns-prefetch" href="http://d.rimg.com.tw">
<link rel="dns-prefetch" href="http://e.rimg.com.tw">

DNS Prefetch

多7次DNS Prefetch,其中不需做DNS Prefetch的有7次,完全命中。由於在上一頁的時候保留了DNS Lookup的紀錄,因此省了7次的DNS Lookup。

拿淘寶的商品頁來看看

DNS Prefetch

先點這個範例頁面

DNS Prefetch

再點這個範例頁面

多9次DNS Prefetch,其中不需做DNS Prefetch的有4次,大約減少了一半。

附註:可以用來觀察結果的指令

  • chrome://histograms/DNS.PrefetchQueue
  • about:histograms/DNS (可看更詳細的資料)
  • about:dns (可看更詳細的資料)

使用DNS Prefetching的好處?

花小量的傳輸(不到100 bytes),卻平均可節省200ms。
(有興趣的話可參考DNS Prefetching - The Chromium Projects)

對SEO來說,網站速度也是Ranking Factor之一,提高下載速度就可提高排名。

減少DNS Lookup 次數的相關議題

假設在頁面上有許多資源,例如:圖片、CSS檔案、JS檔案,這些都放在同一個domain name底下,這時瀏覽器針對每個domain只會開一個連線。也就是說,假設有10個檔案放在同一個domain之下,每個檔案需要100ms才能下載完,那個預計載完資源需要 10*100=1000ms 。但若我們將這10個檔案分別放在2個不同的domain下,就可以開兩條連線檔案同時下載,那麼只要花 5*100=500ms 即可,減少了一半的時間。但也不是說domain愈多愈好,因為DNS Lookup需要時間,因此建議維持2~4個不同的domain name即可。

瀏覽器比較:Chrome、Firefox、IE

Chrome

  1. Chrome會記住最近使用的10個domain,並且在開啟瀏覽器時自動解析,因此在開啟這些常用頁面的時候,並不會有DNS Lookup的延遲狀況,大約節省了200ms或更多。打開你的Chrome,使用指令 chrome://dns 來看看。
  2. 本機作業系統對DNS的快取是有限的,大約只能暫存50~200個domain name。一旦超過了這個限制,便會移除過去使用過的domain name來存放新的domain name。而選取移除的domain name只靠瀏覽的時間決定,可能會造成經常使用的domain name查詢結果被移除,被迫常常對這個domain name進行查詢。Chrome嘗試修正這樣的機制,所以會猜測哪些domain name是使用者近期可能會用到的,然後標記為常用,使其能保存久一點。

(有興趣的話可參考可參考 DNS Prefetching - The Chromium Projects)。

而Chrome類似其他瀏覽器的其他設定都已忽略,似乎不希望使用者更改預設值。因此直接清除。

  1. chrome打開:chrome://net-internals/#dns
  2. 點擊按鈕「clean host cache」

Firefox

  • network.dns.disablePrefetch:若設定為true,則會關閉瀏覽器DNS Prefethcing的功能。
  • network.dns.disablePrefetchFromHTTPS:若設定為false,則會開啟使用HTTPs的網站的DNS Prefethcing功能。在HTTPs的網站下,DNS Prefethcing功能預設是關閉的,必須經此手動開啟。
  • network.dnsCacheExpiration:預設DNS暫存1分鐘
  • network.dnsCacheEntries:預設DNS暫存20個
  • network.http.keep-alive.timeout:TCP/IP連線idle一段時間後才會被釋放掉,預設是5分鐘。好處是避免重覆DNS Lookup太快發生。

IE

  • DnsCacheTimeout:預設DNS暫存30分鐘。
  • KeepAliveTimeout:TCP/IP連線idle一段時間後才會被釋放掉,預設是1分鐘。好處是避免重覆DNS Lookup太快發生。
  • ServerInfoTimeout:就算沒有KeepAliveTimeout,假設我們查到了IP位置,並在使用一段時間內都沒有發生錯誤,那麼這段間內都不會對此domain name做DNS Lookup。預設是2分鐘。

References


由於部落格搬家了,因此在新落格也放了一份,未來若有增刪會在這裡更新-DNS Prefetching - 預先做 DNS 解析,幫助網頁載入速度更快

留言