一、前言
網路優化是客戶端幾大技術方向中公認的一個深度領域,所以百度App給大家帶來網路深度優化系列文章,其中包含系列《一》DNS優化,系列《二》連線優化,系列《三》弱網優化,希望對大家在網路方向的學習和實踐有所幫助。
百度起家於搜尋,整個公司的網路架構和部署都是基於標準的internet協議,目前已經是全棧HTTPS,來到移動網際網路時代後,總的基礎架構不變,但在客戶端上需要做很多優化工作。
DNS(Domain Name System),它的作用是根據域名查出IP地址,它是HTTP協議的前提,只有將域名正確的解析成IP地址後,後面的HTTP流程才能進行,所以一般做網路優化會首選優化DNS。
二、背景
DNS優化核心需要解決的問題有兩點:
【1】由於DNS劫持或故障造成的服務不可用,進而影響使用者體驗,影響公司的收入。
【2】由於DNS排程不準確導致的效能退化,進而影響使用者體驗。
百度App承載著億級流量,每年都會遇到運營商DNS劫持或運營商DNS故障,整體影響非常不好,所以DNS優化刻不容緩,通過下圖會更直觀的瞭解。
三、HTTPDNS
既然我們面臨這麼嚴峻的問題,那麼我們如何優化DNS呢?答案就是HTTPDNS。
大部分標準DNS都是基於UDP與DNS伺服器互動的,HTTPDNS則是利用HTTP協議與DNS伺服器互動,繞開了運營商的Local DNS服務,有效防止了域名劫持,提高域名解析效率,下圖是HTTPDNS的原理。
百度App HTTPDNS端上的實現是基於百度SYS團隊的HTTPDNS服務,下圖介紹了HTTPDNS的服務端部署結構。
HTTPDNS服務是基於BGP接入的,BGP英文Border Gateway Protocol,即邊界閘道器協議,是一種在自治系統之間動態的交換路由資訊的路由協議,BGP可以根據當前使用者的運營商路由到百度服務點的對應叢集上,對於第三方域名,服務點會通過百度部署在運營商的CDN節點向其他域名權威DNS發起查詢,查詢這個運營商下域名的最優IP。
百度App獨立實現了端的HTTPDNS SDK,下圖介紹了端HTTPDNS的整體架構。
DNS介面層:
DNS介面層解決的問題是遮蔽底層的細節,對外提供簡單整潔的API,降低使用者的上手成本,提高開發效率。
DNS策略層:
DNS策略層通過多種策略的組合,使HTTPDNS服務在效能,穩定性,可用性上均保持較高的水準,下面講解下每個策略設計的初衷和具體實現
1.容災策略
這是一個非常關鍵的策略,主要解決HTTPDNS服務可用性的問題,實踐證明,這個策略幫助百度App在異常情況下挽救回很多流量。
【1】當HTTPDNS服務不可用並且本地也沒有快取或者快取失效的時候,會觸發降級策略,降級成運營商的localDNS方案,雖然存在運營商事故或者劫持的風險,但保障了DNS服務的可用性。
【2】當HTTPDNS服務和localDNS服務雙雙不可用的情況下,會觸發backup策略,使用端上的backup IP。
什麼是backup IP?backup IP是多組根據域名分類的IP列表,可雲端動態更新,方便後續運維同學調整服務端的節點IP,不是所有域名都有對應的backup IP列表,目前百度App只能保證核心域名的可用性。
既然是一組IP,便有選取問題,backup IP選取機制是怎樣的呢?我們的中心思想就是要在端上利用最小的代價,並且考慮服務端的負載均衡,得到相對正確或者合理的選取結果。通過運營商和地理資訊,可以選擇一個相對較優的IP,但獲取地理資訊需要很大耗時,外加頻次很高,代價很大,所以我們選擇了RR演算法來代替上面的方法(RR演算法是Round-Robin,輪詢排程),這樣客戶端的代價降低到最小,服務端也實現了負載均衡。
2.安全策略
【1】HTTPDNS解決的核心問題就是安全,標準的DNS查詢大部分是基於UDP的,但也有基於TCP的,如果UDP被封禁,就需要使用TCP。不管是UDP還是TCP,安全性都是沒有保障的,HTTPDNS查詢是基於標準的HTTP協議,為了保證安全我們會在HTTP上加一層TLS(安全傳輸層協議),這便是HTTPS。
【2】解決了傳輸層協議的安全性後,我們要解決下域名解析的問題,上面我們提到HTTPDNS服務是基於BGP接入的,在端上採用VIP方式請求HTTPDNS資料(VIP即Virtual IP,VIP並沒有與某裝置存在必定的繫結關係,會跟隨主備切換之類的情況發生而變換,VIP提供的服務是對應到某一臺或若干臺伺服器的),既然請求原始資料需要使用IP直連的方式,那麼就擺脫了運營商localDNS的解析限制,這樣即使運營商出現了故障或者被劫持,都不會影響百度App的可用性。
3.任務排程策略
HTTPDNS服務提供了兩類HTTP介面,用於請求最優域名結果。第一種是多域名介面,針對不同的產品線,下發產品線配置的域名,第二種是單域名介面,只返回你要查詢的那個域名結果,這樣的設計和標準的DNS查詢基本是一樣的,只不過是從UDP協議變成了HTTP協議。
【1】多域名介面會在App冷啟動和網路切換的時候請求一次,目的是在App的網路環境初始化或者變化的時候預先獲取域名結果,這樣也會減少單域名介面的請求次數。
【2】單域名介面會在本地cache過期後,由使用者的操作觸發網路請求,進而做一次單域名請求,使用者這次操作的DNS結果會降級成localDNS的結果,但在沒有過期的情況下,下次會返回HTTPDNS的結果。
4.IP選取策略
IP選取策略解決的核心問題是最優IP的選取,避免因為接入點的選取錯誤造成的跨運營商耗時。HTTPDNS服務會將最優IP按照順序下發,客戶端預設選取第一個,這裡沒有做客戶端的連通性校驗的原因,主要還是擔心端上的效能問題,不過有容災策略兜底,綜合評估還是可以接受的。
5.快取策略
大家對於DNS快取並不陌生,它主要是為了提升訪問效率,作業系統,網路庫等都會做DNS快取。
DNS快取中一個重要的概念就是TTL(Time-To-Live),在localDNS中針對不同的域名,TTL的時間是不一樣的,在HTTPDNS中這個值由服務端動態下發,百度App目前所有的域名TTL的配置是5分鐘,過期後如果沒有新的IP將繼續沿用老的IP,當然也可以選擇不沿用老的IP,而降級成localDNS的IP,那麼這就取決於localDNS對於過期IP的處理。
6.命中率策略
如果HTTPDNS的命中率是100%,在保證HTTPDNS服務穩定高效的前提下,我們就可以做到防劫持,提升精準排程的能力。
【1】為了提升HTTPDNS的命中率,我們選擇使用多域名介面,在冷啟動和網路切換的時候,批量拉取域名結果並快取在本地,便於接下來的請求使用。
【2】為了再一次提升HTTPDNS的命中率,當使用者操作觸發網路請求,獲取域名對應的IP時,會提前進行本地過期時間判斷,時間是60s,如果過期,會發起單域名的請求並快取起來,這樣會持續延長域名結果的過期時間。本地過期時間與上面提到的TTL是客戶端和服務端的雙重過期時間,目的是在異常情況下可以雙重保證過期時間的準確性。
基礎能力層:
基礎能力層主要提供給DNS策略層所需要的基礎能力,包括IPv4/IPv6協議棧探測的能力,資料傳輸的能力,快取實現的能力,下面將講解每種能力的具體實現
1.IPv4/IPv6協議棧探測:
百度App的IPv6改造正在如火如荼的進行中,端上在HTTPDNS的IP選取上如何知道目前屬於哪個協議棧成為關鍵性問題,並且這種判斷要求效能極高,因為IP選取的頻次實在是太高了。
我們選取的方案是UDP Connect,那麼何為UDP Connect?大家都知道TCP是面向連線的,傳輸資料前客戶端都要呼叫connect方法通過三次握手建立連線,UDP是面向無連線的,無需建立連線便能收發資料,但是如果我們呼叫了UDP的connect方法會發生什麼呢?當我們呼叫UDP的connect方法時,系統會檢測其埠是否可用,地址是否正確,然後記錄對端的IP地址和埠號,返回給呼叫者,所以UDP Connect不會像TCP Connect發起三次握手,發生網路真實損耗,UDP客戶端只有呼叫send或者sendto方法後才會真正發起真實網路損耗。
有了UDP Connect的基礎保障,我們在上層做了快取機制,用來減少系統呼叫的損耗,時機上目前僅在冷啟動和網路切換會觸發探測,在同一種網路制式下探測一次基本可以確保當前網路是IPv4棧還是IPv6棧。
目前百度App客戶端對於IPv4/IPv6雙棧的策略是保守的,僅在IPv6-only的情況下使用v6的IP,其餘使用的都是v4的IP,雙棧下的方案後續需要優化,業內目前標準的做法是happy eyeball演算法,什麼叫happy eyeball呢?就是不會因為IPv4或IPv6的故障問題,導致使用者的眼球一直在等待載入或者出錯,這就是happy eyeball名字的由來。happy eyeball有v1版本RFC6555和v2版本RFC8305,前者是Cisco提出來的,後者是蘋果提出來的。happy eyeball解決的核心問題是,複雜環境下v4和v6 IP選取的問題,它是一套整體解決方案,對於域名查詢的處理,地址的排序,連線的嘗試等方面均做出了規定,感興趣的同學可以檢視參考資料裡的【5】和【6】。
2.資料傳輸:
資料傳輸主要提供網路請求的能力和資料解析的能力。
【1】網路請求失敗重試的機制,獲取HTTPDNS結果的成功率會大大影響HTTPDNS的命中率,所以客戶端會有一個三次重試的機制,保障成功率。
【2】資料解析異常的機制,如果獲取的HTTPDNS的結果存在異常,將不會覆蓋端上的快取。
3.快取實現:
快取的實現基本可以分為磁碟快取和記憶體快取,對於HTTPDNS的快取場景,我們是選其一還是都選擇呢?百度App選擇的是記憶體快取,目的是防止我們自己的服務出現問題,運維同學在緊急情況下切換流量,如果做了磁碟快取,會導致百度App在重啟後也可能不可用,但這種問題會導致APP在冷啟動期間,HTTPDNS結果未返回前,還是存在故障或者劫持的風險,綜合評估來看可以接受,如果出現這種極端情況,影響的是冷啟動階段的一些請求,但只要HTTPDNS結果返回後便會恢復正常。
四、HTTPDNS的最佳實踐
百度App目前客戶端網路架構由於歷史原因還未統一,不過我們正朝著這個目標努力,下面著重介紹下HTTPDNS在Android和iOS網路架構中的位置及實踐。
HTTPDNS在Android網路架構的位置及實踐
百度App的Android網路流量都在okhttp之上,上層進行了網路門面的封裝,封裝內部的實現細節和對外友好的API,供各個業務和基礎模組使用,在okhttp上我們擴充套件了DNS模組,使用HTTPDNS替換了原有的系統DNS。
HTTPDNS在iOS網路架構的位置及實踐
百度App的iOS網路流量都在cronet(chromium的net模組)之上,上層我們使用AOP的方式將cronet stack注入進URLSession裡,這樣我們就可以直接使用URLSession的API進行網路的操作而且更易於系統維護,在上層封裝了網路門面,供各個業務和基礎模組使用,在cronet內部我們修改了DNS模組,除了原有的系統DNS邏輯外,還新增了HTTPDNS的邏輯。iOS上還有一部分流量是在原生URLSession上,主要是有些第三方業務沒有使用cronet但還想單獨使用HTTPDNS的能力,所以就有了下面的HTTPDNS封裝層,方法是在上層直接將域名替換成IP,域名對於底層很多機制是至關重要的,比如https校驗,cookie,重定向,SNI(Server Name Indication)等,所以將域名修改成了IP直連後,我們又處理了以上三種情況,保證請求的可用性。
五、收益
DNS優化的收益主要有兩點,一是防止DNS的劫持(在出問題時顯得尤為重要),降低網路時延(在排程不準確的情況下,會增大網路的時延,降低使用者的體驗),這兩點收益需要結合業務來說,以百度App Feed業務為例,第一點上我們取得了比較大的效果,iOS劫持率由0.12%降低到0.0002%,Android劫持率由0.25%降低到0.05%,第二點的收益不明顯,原因在於Feed業務主要目標群體在國內,百度在國內節點佈局相對豐富,服務整體質量也較高,即使出現排程不準確的情況,差值也不會太大,但如果在國外情況可能會差很多。
六、結語
DNS優化是個持續性的話題,上面介紹的百度App的一些經驗和做法並不見得完美,但我們會持續深入的優化下去,為百度App的DNS能力保駕護航。最後感謝大家的辛苦閱讀,希望對你有所幫助,後面會繼續推出-百度App網路深度優化系列《二》連線優化,敬請期待。
七、個人心得
做為一個工程師,如何才能做好網路優化這件事情,是個值得我們交流探討的話題,個人認為應該從以下五方面入手。
【1】基礎知識要了解學習,要夯實,網路相關的內容很多,很雜,不易學習,啃過IETF釋出的RFC的同學應該深有感觸。
【2】學會將看不見的網路變成看得見的,很多自認為對於網路很瞭解的同學,動不動就背誦tcp協議原理,擁塞控制演算法,滑動視窗大小等,但真正遇到線上問題,無從下手。對於客戶端同學,我們在PC上要學會使用tcpdump和Wireshark等工具,適當使用Fiddler和Charles等工具,很多時候電腦和手機的網路環境不見得一致,所以要在手機上使用iNetTools,Ping&DNS或終端工具。學會使用工具後,要學著創造不同的網路環境,有很多工具能幫助你完成這點,比如蘋果的Network Link Conditioner,FaceBook的ATC(Augmented Traffic Control)等。具備以上兩個場景後,你的第一條儲備就發揮了作用,你要能看懂握手過程,傳輸過程,異常斷開過程等。
【3】有了以上兩點的準備,接下來需要一個會出現各種網路問題的平臺,給你積累經驗,讓一個個高壓下的線上問題錘鍊你,折磨你。
【4】網路優化是需要資料支撐的,但資料的採集和分析是需要經驗的,有些資料一眼看下去就是不靠譜的,有些資料怎麼分析都是負向收益的,一般來說是有三重奏來對資料進行分析的,一,線下資料的採集和分析,得出正向收益,二,灰度資料的採集和分析,得出正向收益,三,線上資料的採集和分析,得出正向收益。
【5】資料的正向收益,不能完全證明提升了使用者的體驗,所以很多時候需要針對特定場景,特定case來分析和優化,就算是大家公認做的很好的微信,也不是在所有場景下都能保證體驗上的最佳。
八、參考資料
- https://chromium.googlesource...
- https://chromium.googlesource...
- https://github.com/Tencent/mars
- https://tools.ietf.org/html/r...
- https://tools.ietf.org/html/r...
- https://tools.ietf.org/html/r...
本文作者:
蔡銳
在微信-搜尋頁面中輸入“百度App技術”,即可關注微信官方賬號;或使用微信識別以下二維碼,亦可關注。