一、前言
IPv6是當下如火如荼的話題,由於IPv4地址的耗盡,所以IPv6的切換已經勢在必行。但在IPv6的初期,由於基礎建設還不完善,IPv6可能會出現連通性或可靠性的問題,那我們該如何從IPv4平穩過渡到IPv6呢?
目前業內標準的做法叫Happy Eyeballs,什麼叫Happy Eyeballs呢?就是不會因爲IPv4或IPv6的故障問題,導致用戶的眼球一直在等待加載或者出錯,這就是Happy Eyeballs名字的由來。
二、背景
Happy Eyeballs解決的核心問題是,複雜環境下v4和v6 IP選取的問題,它是一套整體解決方案,對於域名查詢的處理,地址的排序,連接的嘗試等方面均做出了規定。
Happy Eyeballs有v1版本RFC6555(Cisco提出來的)和v2版本RFC8305(Apple提出來的)。具體的協議規範可參考資料【1】和【2】。我們從百度App對於Happy Eyeballs的實踐出發,剖析下百度App是如何實現Happy Eyeballs的。
三、最佳實踐
百度App的Happy Eyeballs最佳實踐,如下圖所示。
最佳實踐包括自有業務和核心組件(圖片組件,音視頻組件,WebView組件)底層網絡庫的流量接管。
網絡庫包括FFmpeg的網絡模塊(實現了RFC8305的Happy Eyeballs),okhttp(實現了RFC6555的Happy Eyeballs),統一網絡庫cronet(實現了RFC6555的Happy Eyeballs)。下面我們來看下這三個網絡庫的Happy Eyeballs的實現機制。
1.FFmpeg的Happy Eyeballs實現機制
我們從域名查詢的處理、地址的排序、連接的嘗試三個方面來說明。
域名查詢的處理,FFmpeg主要流量走的是localDNS,會將v4和v6地址一併查詢回來,DNS query中A記錄表示v4查詢,Type是1,AAAA記錄表示v6查詢,Type是28。具體協議可以參考下面兩圖。
地址的排序,如果查詢回來是多個v4和v6的地址,會將查詢結果保存在addrinfo這個結構體裏,它是一個鏈表結構,會將這個鏈表交替排序,v6在前,v4在後,比如查詢回來的是[第一個v4地址,第二個v4地址,第一個v6地址,第二個v6地址],排序之後變成[第一個v6地址,第一個v4地址,第二個v6地址,第二個v4地址]。
連接的嘗試,立即連接v6地址,FFmpeg可以讓使用者設置連接超時時間,會將這個超時時間和200ms(這是RFC8305建議的值)進行取小操作,如果在較小值以內v6建連成功,則結束,若以外將發起下一個v4連接,與此同時關閉當前的v6連接。延遲發送的v4連接將重複上面的操作,如果成功則結束,如果超時將發起下一個v6連接,與此同時關閉當前的v4連接。直到沒有ip地址。
2.cronet的Happy Eyeballs實現機制
我們從域名查詢的處理、地址的排序、連接的嘗試三個方面來說明。
域名查詢的處理,百度App的cronet主要流量走的是HTTPDNS,HTTPDNS請求會將一個域名的v4地址和v6地址同時返回。
地址的排序,cronet開啓Happy Eyeballs有兩個條件,一是查詢結果第一個地址是v6的,二是查詢結果裏包含v4和v6的地址。cronet會優先將v6地址放入結果列表,保證了第一點。
連接的嘗試,立即連接v6地址並開啓一個延遲300ms(這是RFC6555建議的值)發起v4的建連任務,如果在300ms以內v6建連成功,延遲任務直接終止,流程結束。若以外會將結果列表進行rotate,按順序將列表裏的第一個v4地址旋轉到第一個,發起v4連接,此時將開啓一個競爭模式,當v4開始建立連接和建連成功後,都會去檢查v6是否成功,只要v6在競爭模式內建連成功,則使用v6的連接,v6沒有建連成功,則使用v4連接。
3.okhttp的Happy Eyeballs實現機制
百度App依照cronet的實現細節,遵循RFC6555的規範,實現了okhttp版本的Happy Eyeballs,由於實現細節和cronet類似,所以就不在這裏進行講解。主體流程如上圖,通過okhttp的請求併發控制模塊(核心定義了最大線程數64個和單域名的最大併發數5個),再來到核心攔截器模塊,包括對於Header和Cookie處理的攔截器,對於Cache處理的攔截器,對於連接處理的攔截器,在連接處理的攔截器裏首先是從連接池獲取連接,獲取不到就會新創建連接,Happy Eyeballs的實現就會加到這裏。
4.WKWebView的Happy Eyeballs實現
在某些場景下WKWebView沒有被cronet網絡庫進行接管,所以還需要依賴蘋果自身的Happy Eyeballs機制,在這裏就不多贅,感興趣的同學可以參考資料【3】,蘋果的工程師會詳細講解如何實現Happy Eyeballs的機制以及Happy Eyeballs下走v6的測試結果。
四、結語
IPv6的進程是任重而道遠的,Happy Eyeballs做爲從v4過渡到v6的重要規範必然會起到它應有的使命,詳盡瞭解它並使用它應該是每個相關工程師的職責,希望本次番外篇對大家有幫助,感謝大家的辛苦閱讀。
參考資料
[1]https://tools.ietf.org/html/rfc6555
[2]https://tools.ietf.org/html/rfc8305
[3]https://mailarchive.ietf.org/arch/msg/v6ops/DYiI9v_O66RNbMJsx0NsatFkubQ
[4]https://git.ffmpeg.org/gitweb/ffmpeg.git/commit/9b4c3f5aadf54ffd2a6e15746b1fd736379883c4
作者介紹:
蔡銳,9 年移動端開發經驗,在百度先後主導過訂製 ROM 領域、多屏互動領域、Hybrid 跨平臺領域等多個技術領域的開發,目前擔任百度 App 的客戶端資深工程師,參與基礎技術的研究,專攻動態化、性能和網絡優化方向。獲得2019軟件綠色聯盟最佳人氣講師、2019ArchSummit大前端專題明星講師。
相關文章: