Categories
程式開發

IPv6下Happy Eyeballs的最佳實踐


前言

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最佳實踐,如下圖所示。

IPv6下Happy Eyeballs的最佳實踐 1

Happy Eyeballs最佳實踐

最佳實踐包括自有業務和核心組件(圖片庫,播放內核,瀏覽內核)底層網絡庫的流量接管。

網絡庫包括ijkavformat(ijkplayer的網絡模塊,實現了RFC8305的Happy Eyeballs),okhttp(實現了RFC6555的Happy Eyeballs),統一網絡庫cronet(實現了RFC6555的Happy Eyeballs)。

下面我們來看下這三個網絡庫的Happy Eyeballs的實現機制。

丨1. ffmpeg(ijkplayer不准確)的Happy Eyeballs實現機制

我們從域名查詢的處理,地址的排序,連接的嘗試三個方面來說明。

IPv6下Happy Eyeballs的最佳實踐 2

ijkplayer Happy Eyeballs實現機制

域名查詢的處理,百度App的ijkplayer主要流量走的是localDNS,會將v4和v6地址一併查詢回來,DNS query中A記錄表示v4查詢,Type是1,AAAA記錄表示v6查詢,Type是28。具體協議可以參考下面兩圖。

IPv6下Happy Eyeballs的最佳實踐 3

IPv4的Query

IPv6下Happy Eyeballs的最佳實踐 4

IPv6的Query

地址的排序,如果查詢回來是多個v4和v6的地址,會將查詢結果保存在addrinfo這個結構體裡,它是一個鍊錶結構,會將這個鍊錶交替排序,v6在前,v4在後,比如查詢回來的是(第一個v4地址,第二個v4地址,第一個v6地址,第二個v6地址),排序之後變成(第一個v6地址,第一個v4地址,第二個v6地址,第二個v4地址)。

連接的嘗試,立即連接v6地址,ijkplayer可以讓使用者設置連接超時時間,會將這個超時時間和200ms(這是RFC8305建議的值)進行取小操作,如果在較小值以內v6建連成功,則結束,若以外將發起下一個v4連接,與此同時關閉當前的v6連接。延遲連接v4地址將重複上面的操作,如果成功則結束,如果超時將發起下一個v6連接,與此同時關閉當前的v4連接。直到沒有ip地址。

丨2. cronet的Happy Eyeballs實現機制

我們從域名查詢的處理,地址的排序,連接的嘗試三個方面來說明。

IPv6下Happy Eyeballs的最佳實踐 5

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實現機制

IPv6下Happy Eyeballs的最佳實踐 6

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的重要規範必然會起到它應有的使命,詳盡了解它並使用它應該是每個相關工程師的職責,希望本次番外篇對大家有幫助,感謝大家的辛苦閱讀。

本文轉載自公眾號百度App技術。

原文鏈接

https://mp.weixin.qq.com/s?__biz=MzUxMzk2ODI1NQ==&mid=2247483915&idx=1&sn=ce1140c3911f2e202a693726116b174d&chksm=f94c531bce3bda0d85134f9647aab58b92c50552d6b694470807dc005ca2c5c9acb2ca7928a5&scene=27#wechat_redirect