前言
翻閱網上資料,很難找到一篇文章能夠把HttpDNS和傳統DNS之間的區別講述的通俗易懂的,偶然間在極客時間看到劉超老師講的趣談網絡協議,對HttpDNS和傳統DNS的區別有了更深一步的認識,大家如果需要可以有空去學習下劉超老師講的"趣談網絡協議",相信對大家了解網絡協議大有益處。
傳統DNS存在哪些問題
域名緩存問題
域名解析的結果可以在本地做一個緩存,也就是說,不是每一個請求都會去訪問權威DNS服務器,而是訪問過一次就把結果緩存到本地,當其他人來問的時候,直接就返回這個緩存數據。
這就相當於導游去過一個飯店,自己腦子記住了地址,當有一個游客問的時候,他就憑記憶回答了,不用再去查地址薄,這樣經常存在一個問題,人家那個飯店明明已經搬了,結果作為導游,他並沒有刷新這個緩存,結果你辛辛苦苦到了這個 地點,發現飯店已經變成了服裝店,你是不是非常失望
另外,有的運營商會把一些靜態頁面,緩存到本地運營商的服務器內,這樣用戶請求的時候,就不用跨運營商進行訪問,這樣既加快了速度,也減少了運營商之間的流量計算的成本。在域名解析的時候,不會將用戶導向真正的網站,而是指向這個緩存的服務器。
很多情況下是看不出問題的,但是當頁面更新,用戶訪問到老的頁面,問題就出來了。例如,你聽說餐館推出了一個新菜,你想去嘗一下,結果導游告訴你,在這里吃也是一樣的,有的游客會覺得沒問題,但是對於想嘗試新菜的人來說,但是導游說帶你去,但其實並沒有吃到新菜,你是不是也會非常失望呢?
再就是本地緩存,往往使得全局負載均衡失敗,因為上次進行緩存的時候,緩存中的地址不一定是這次訪問離客戶最近的地方,如果把這個地址返回給客戶,那肯定就會繞遠路。
就像上一次客戶要吃西湖醋魚的事,導游知道西湖邊有一家,因為當時游客就在西湖邊,可是,下一次客戶在靈隱寺,想吃西湖醋魚的時候,導游還指向西湖邊的那一家,那這就繞得太遠了。
域名轉發問題
緩存問題還是說本地域名解析服務,還是會去權威DNS服務器中查找,只不過不是每次都要查找。可以說這還是大導游、大中介。還有一些小導游、小中介,有了請求之后,直接轉發給其它運營商去做解析,自己只是外包了出去。
這樣的問題是,如果是A運營商的客戶,訪問自己運營商的DNS服務器,如果A運營商去權威DNS查詢的話,權威DNS就知道你是A運營商的,就返回給一個部署在A運營商的網站地址,這樣針對相同運營商的訪問,速度就會快很多。
但是A運營商偷懶,將解析的請求轉發給B運營商,B運營商去權威DNS服務器查詢的話,權威服務器會誤認為你是B運營商的,那就返回給你一個在B運營商的網站地址,結果客戶的每次訪問都要跨運營商,速度就會很慢。
前面講述網關的時候,我們知道,出口的時候,很多機房都會配置NAT,也即網絡地址轉換,使得從這個網關出去的包,都換成新的IP地址,當然請求返回的時候,在這個網關,再將IP地址轉換回去,所以對於訪問來說是沒有任何問題。
但是一旦網絡做了網絡地址轉換,權威DNS服務器就沒辦法通過這個地址來判斷客戶到底是來自哪個運營商,而且極有可能因為轉換過后的地址,誤判運營商,導致跨運營商訪問。
域名更新問題
本地DNS服務器是由不同地區、不同運營商獨立部署的。對域名解析緩存的處理及實現策略也有區別,有的會偷懶,忽略域名解析結果的TTL時間限制,在權威DNS服務器解析變更的時候,解析結果在全網生效的周期非常漫長。但是有的時候,在DNS的切換中,場景對生效時間要求比較高。
例如雙機房部署的時候,跨機房的負載均衡和容災多使用DNS來做。當一個機房出問題之后,需要修改權威DNS,將域名指向新的IP地址,但是如果更新太慢,那很多用戶都會出現訪問異常。
這就像,有的導游比較勤快、敬業、時時刻刻關注酒店、參觀、交通的變化,問他的時候,往往會得到最新情況。有的導游懶一些。8年前背的導游詞就沒換過,問他的時候,指的路往往就是錯的。
解析延遲問題
我們知道,從DNS查詢的過曾來看,DNS的查詢需要遞歸遍歷多個DNS服務器才能獲得最終的解析結果,這會帶來一定的延遲,甚至會解析超時。
HttpDNS的工作模式
既然DNS解析中有這么多問題,那該怎么辦呢?難不成回退到直接用IP地址?這樣顯然不合適,所以就有了HttpDNS
HttpDNS其實就是不走傳統的DNS解析,而是自己搭建基於HTTP協議的DNS服務器集群,分布在多個地點和多個運營商。當客戶端需要DNS解析的時候,直接通過HTTP協議進行請求這個服務集群,得到就近的地址。
這就相當於每家基於HTTP協議,自己實現自己的域名解析,自己做一個自己的地址薄,而不使用統一的地址簿。但是默認的域名解析都是走DNS的,因而使用HttpDNS需要繞過默認的DNS路徑,就不能使用默認的客戶端。使用HttpDNS的,往往是手機應用,需要在手機端嵌入支持HttpDNS的客戶端SDK。
通過自己的HttpDNS服務器和自己的SDK,實現了從依賴本地導游,到自己上網查詢做旅游攻略,進行自由行,愛怎么玩就怎么玩。這樣就能夠避免依賴導游,而導游又不專業,你還不能把它怎么樣的尷尬
下面我們來講解一下HttpDNS的工作模式
在客戶端的SDK里動態請求服務端,獲取HttpDNS服務器的IP列表,緩存到本地,隨着不斷的解析域名,SDK也會在本地緩存DNS域名解析的結果。
當手機應用要訪問一個地址的時候,首先看是否有本地的緩存,如果有就直接返回。這個緩存和本地DNS的緩存不一樣的是,這個手機應用自己做的,而非整個運營商統一做的。如何更新、何時更新,手機應用的客戶端可以和服務器協調來做這件事情。
如果本地沒有,就需要請求HttpDNS的服務器,在本地HttpDNS服務器的IP列表中,選擇一個發出HTTP的請求,會返回一個要訪問網站的IP列表。
請求的方式是這樣的。
curl http://106.2.xxx.xxx/d?dn=c.m.163.com
{"dns":[{"host":"c.m.163.com","ips":["223.252.199.12"],"ttl":300,"http2":0}],"client":{"ip":"106.2.81.50","line":269692944}}
手機客戶端自然知道手機在哪個運營商、哪個地址。由於是直接HTTP通信,HttpDNS服務器能夠准確知道這些信息,因而可以做精准的全局負載均衡。
當然,當所有這些都不工作的時候,可以切換到傳統的LocalDNS來解析,慢也比訪問不到好。那HttpDNS是如何解決上面的問題的呢?
其實歸結起來就是兩大問題。一是解析速度和更新速度的平衡問題,二是智能調度的問題,對應的解決方案是HttpDNS的緩存設計和調度設計。
HttpDNS的緩存設計
解析DNS過程復雜,通信次數多,對解析速度造成很大的影響。為了加快解析,因而有了緩存DNS,但是這又會產生緩存更新速度不及時的問題。最要命的是,這兩個方面都掌握在別人手中,也即本地DNS服務器手中,它不會為你定制,你作為客戶端干着急沒辦法。
而HttpDNS就是將解析速度和更新速度全部掌握在自己手中。一方面,解析的過程不需要本地DNS服務遞歸的調用一大圈,一個HTTP的請求直接搞定,要實時更新的時候,馬上就能起作用;另一方面為了提高解析速度,本地也有緩存,緩存是在客戶端SDK維護的,過期時間、更新時間,都可以自己控制。
HttpDNS的緩存設計策略也是咱們做應用框架中常用的緩存設計模式,也即分為客戶端、緩存、數據源三層。
- 對於應用架構來講,就是應用、緩存、數據庫。常見的是Tomcat、Redis、MySQl。
- 對於HttpDNS來將,就是手機客戶端、DNS緩存、HttpDNS服務器
只要是緩存模式,就存在緩存的過期、更新、不一致的問題,解決思路也是很像的。
例如DNS緩存在內存中,也可以持久化到存儲上,從而APP重啟之后,能夠盡快從存儲中加載上次累計的經常訪問的網站的解析結果,就不需要每次都全部解析一遍,再變成緩存。這有點像Redis是基於內存的緩存,但是同樣提供持久化的能力,使得重啟或者主備切換的時候,數據不會完全丟失。
SDk中的緩存會嚴格按照緩存過期時間,如果緩存沒有命中,或者已經過期,而且客戶端不允許使用過期的緩存記錄,則會發起一次解析,保障記錄時更新的。
解析可以同步進行,也就是直接調用HttpDNS的接口,返回最新的記錄,緩存更新;也可以異步進行,添加一個解析任務到后台,有后台任務調用HttpDNS的接口。
同步更新的優點是實時性好,缺點是如果有多個請求都發現過期的時候,同時會請求HttpDNS多次,其實是一種浪費。
同步更新的方式對應到應用架構中緩存的Cache-Aside機制,也即先讀緩存,不命中讀數據庫,同時將結果寫入緩存。
異步更新的優點是,可以將多個請求都發現過期的情況,合並為一個對於HttpDNS的請求任務,只執行一次,減少HttpDNS的壓力。同時可以在即將過期的時候,就創建一個任務進行預加載,防止過期之后再刷新,稱為預加載
異步更新的缺點是當前請求拿到過期數據的時候,如果客戶端允許使用過期數據,需要冒一次風險。如果過期的數據還能請求,就沒問題;如果過期的數據不能請求,則失敗一次,等下次緩存更新后,再請求方能成功。
異步更新的機制對應到應用架構緩存的Refresh-Ahead機制,即業務僅僅訪問緩存,當過期的時候定期刷新。在著名的應用緩存Guava Cache中,有個RefreshAfterWrite機制,對於並發情況下,多個緩存訪問不命中從而引發並發回源的情況,可以采取只有一個請求回源的模式。在應用架構的緩存中,也常常用數據預熱或者預加熱的機制。
HttpDNS的調度設計
由於客戶端嵌入了SDK,因而就不會因為本地DNS的各種緩存、轉發、NAt,讓權威DNS服務器誤會客戶端所在的位置和運營商,而可以拿到第一手資料。
在客戶端,可以知道手機是哪個國家、哪個運營商、哪個省,甚至哪個市,HttpDNS服務器端可以根據這些信息,選擇最佳的服務節點返回。
如果有多個節點,還會考慮錯誤率、請求時間、服務器壓力、網絡狀況等,進行綜合選擇,而非僅僅考慮地理位置。當有一個節點宕機或者性能下降的時候,可以盡快進行切換。
要做到這一點,需要客戶端使用HttpDNS返回的IP訪問業務應用。客戶端的SDK會收集網絡請求數據,如錯誤率、請求時間等網絡請求質量數據,並發送到統計后台,進行分析,聚合,以此查看不同的IP的服務質量。
在服務器端,應用可以通過調用HttpDNS的管理接口,;配置不同服務質量的優先級、權重。HttpDNS會根據這些策略綜合地理位置和線路狀況算出一個排序,優先訪問當前那些優質的,時延低的IP地址。
HttpDNS通過智能調度之后返回的結果,也會緩存在客戶端。為了不讓緩存使得調度失真,客戶端可以根據不同運營商WIFI的SSID來分維度緩存。不同的運營商或者WIFi解析出來的結果會不同
問題思考
- 使用HttpDNS,需要向HttpDNS服務器請求解析域名,可是客戶端怎么知道HttpDNS服務器的地址或者域名呢?
解答: HttpDNS服務器的地址一般不變,可以使用DNS的方式獲取HttpDNS服務器的IP地址,也可以直接把httpdns服務器的ip地址寫死在客戶端中 - HttpDNS的智能調度,主要是讓客戶端選擇最近的服務器,而有另一種機制,使得資源分發到離客戶端更近的位置,從而加快客戶端的訪問,你知道是什么技術么?
解答:為方便用戶資源就近訪問,使用CDN技術.