攜程App網路服務通道治理和效能優化

錢曙光發表於2016-08-08

App網路服務的高可靠和低延遲對於無線業務穩定發展至關重要,過去兩年來我們一直在持續優化App網路服務的效能,到今年Q2結束時基本完成了App網路服務通道治理和效能優化的階段性目標,特此撰文總結其中的經驗教訓,為以後的工作打下基礎。

一、攜程App無線網路服務架構

2014年攜程為無線服務開發了Mobile Gateway,有兩種型別:TCP Gateway和HTTP Gateway。 TCP Gateway設計用於App中Native業務網路服務,基於TCP協議之上設計了應用層協議,類似於RPC機制。TCP Gateway兼具了接入層和服務動態路由的功能,接入層的功能基於Netty實現,管理客戶端的TCP長連線或者短連線;動態路由的功能基於Netfix開源的Zuul實現(Zuul is a gateway service that provides dynamic routing, monitoring, resiliency, security, and more. ),可以在TCP Gateway上實現服務路由、監控、反爬和使用者鑑權等功能。

圖片描述

每個TCP服務請求到達TCP Gateway之後,會根據報文頭中的服務號,轉發到後端對應的業務服務叢集上,從而實現後端服務的解耦。TCP Gateway到後端業務服務叢集之間的轉發使用HTTP協議的介面形式實現,一個TCP服務請求的完整報文會作為HTTP請求的Payload轉發到後端業務服務叢集,接收到HTTP響應後,會將其Payload完整的返回到對應的TCP連線中。

HTTP Gateway用於App中Hybrid和H5 Web站點的網路服務,採用HTTP Restful介面形式提供服務,其邏輯相對簡單,核心是HTTP服務動態轉發的功能。

圖片描述

Mobile Gateway的更多設計實現細節可以參考王興朝同學在2015上海QCon的演講《攜程無線Gateway》。

二、基於TCP協議實現App網路服務

頻寬和延遲是影響網路服務效能的兩個因素,頻寬受網路通道上最小頻寬的網段限制,延遲是網路包在客戶端和服務端之間的來回傳輸時長,不同網路型別上的頻寬和延遲差別非常大(見下圖)。

圖片描述

我們要實現更好效能的網路服務,對於網路自身的頻寬和延遲這兩點而言,能做只是儘可能選擇最合適的網路通道,其他只能在如何使用網路通道上進行優化。

傳統的非IM即時訊息類App通常都是使用HTTP協議來實現網路服務的(Restful API形式),攜程使用TCP協議來實現,確實會增加很多開發成本,例如需要設計應用層協議、管理網路連線、處理異常等,但下面幾點原因還是讓我們最終選擇基於TCP協議來實現App網路服務:

  1. 攜程使用者有時會在網路環境非常差的景區使用,需要針對弱網進行特別的優化,單純HTTP應用層協議很難實現;

  2. HTTP請求首次需要進行DNS域名解析,我們發現國內環境下針對攜程域名的失敗率在2-3%(包含域名劫持和解析失敗的情況),嚴重影響使用者體驗;

  3. HTTP雖然是基於TCP協議實現的應用層協議,優勢是封裝性好,客戶端和服務端解決方案成熟。劣勢是可控性小,無法針對網路連線、傳送請求和接收響應做定製性的優化,即使是HTTP的特性如保持長連線KeepAlive或者管道Pipeline等都會受制於網路環境中的Proxy或者服務端實現,很難充分發揮作用。

基於TCP協議實現可以讓我們能夠完整控制整個網路服務生命週期的各個階段,包括如下幾個階段:

  1. 獲取服務端IP地址
  2. 建立連線
  3. 序列化網路請求報文
  4. 傳送網路請求
  5. 接受網路響應
  6. 反序列化網路響應報文

我們的網路服務通道治理和優化工作就是從這幾個方面展開的。

三、TCP網路服務通道治理和效能優化

1. 告別DNS,直接使用IP地址

如果是首次傳送基於HTTP協議的網路服務,第一件事就是進行DNS域名解析,我們統計過DNS解析成功率只有98%,剩下2%是解析失敗或者運營商DNS劫持(Local DNS返回了非源站IP地址),同時DNS解析在3G下耗時200毫秒左右,4G也有100毫秒左右,延遲明顯。我們基於TCP連線,直接跳過了DNS解析階段,使用內建IP列表的方式進行網路連線。

攜程App內建了一組Server IP列表,同時每個IP具備權重。每次建立新連線,會選擇權重最高的IP地址進行連線。App啟動時,IP列表的所有權重是相同的,此時會啟動一組Ping的操作,根據Ping值的延遲時間來計算IP的權重,這麼做的原理是Ping值越小的IP地址,連線後的網路傳輸延遲也應該相對更小。業界也有使用HTTP DNS方式來解決DNS劫持問題,同時返回最合適使用者網路的Server IP。然而HTTP DNS的開發和部署需要不小的開發成本,我們目前沒有使用。

內建Server IP列表也會被更新,每次App啟動後會有個Mobile Config服務(支援TCP和HTTP兩種網路型別服務)更新Server IP列表,同時支援不同產品線的Server IP列表更新。因此,傳統DNS解析能夠解決多IDC導流的功能也可以通過此方法解決。

2. Socket連線優化,減少連線時間

和HTTP協議中的Keepalive特性一樣,最直接減少網路服務時間的優化手段就是保持長連線。每次TCP三次握手連線需要耗費客戶端和服務端各一個RTT(Round trip time)時間才能完成,就意味著100-300毫秒的延遲;TCP協議自身應對網路擁塞的Slow Start機制也會影響新連線的傳輸效能。

攜程App使用了長連線池的方式來使用長連線,長連線池中維護了多個保持和服務端的TCP連線,每次網路服務發起後會從長連線池中獲取一個空閒長連線,完成網路服務後再將該TCP連線放回長連線池。我們沒有在單個TCP連線上實現Pipeline和Multiplexing機制,而是採用最簡單的FIFO機制,原因有二:1. 簡化Mobile Gateway的服務處理邏輯,減少開發成本;2. 在服務端同時返回多個響應時,如果某個響應報文非常大,使用多個長連線方式可以加快接收服務響應報文速度。

如果發起網路服務時長連線池中的TCP連線都正在被佔用,或者TCP長連線的網路服務失敗,則會發起一個TCP短連線實現網路服務。這裡長連線和短連線的區別僅僅是服務完成後是否直接關閉這個TCP連線。

附:Pipeline和Multiplexing是有區別的,如HTTP/1.1支援Pipeline,客戶端能否同時傳送多個請求,但是服務端返回響應時也要按照請求的傳送次序來返回響應;SPDY和HTTP/2協議支援Multiplexing,即支援響應報文的亂序返回,傳送請求和接收響應互不干擾,因此避免了HTTP/1.1 Pipeline也沒能完全解決的Head of line blocking問題。參考資料:1, 2。參考資歷2中提到HTTP/1.1的Pipeline特性只是部分解決了Head of line blocking問題,因為a large or slow response can still block others behind it。

3. 弱網和網路抖動優化

攜程App引入了網路質量引數,通過網路型別和端到端Ping值進行計算,根據不同的網路質量改變網路服務策略:

1) 調整長連線池個數:例如在2G/2.5G Egde網路下,會減少長連線池個數為1(運營商會限制單個目標IP的TCP連線個數);WIFI網路下可以增加長連線池個數等機制;

2) 動態調整TCP connection、write、read的超時時間;

3) 網路型別切換時,例如WIFI和行動網路、4G/3G切換至2G時,客戶端IP地址會發生變化,已經連線上的TCP Socket註定已經失效(每個Socket對應一個四元組:源IP、源Port、目標IP、目標Port),此時會自動關閉所有空閒長連線,現有網路服務也會根據狀態自動重試。

4. 資料格式優化,減少資料傳輸量和序列化時間

傳輸資料量越小,在相同TCP連線上的傳輸時間越短。攜程App曾經使用自行設計的一套資料格式,後來和Google ProtocolBuffer對比後發現,特定資料型別下資料包大小會降低20-30%,序列化和反序列化時間可以降低10-20%,因此目前核心服務都在逐步遷移到到ProtocolBuffer格式。另外Facebook曾分享過他們使用FlatBuffer資料格式提高效能的實踐,我們分析後不太適合攜程的業務場景因而沒有使用。

5. 引入重試機制,提升網路服務成功率

受TCP協議重傳機制來保證可靠傳輸的機制啟發,我們在應用層面也引入了重試機制來提高網路服務成功率。我們發現90%以上的的網路服務失敗都是由於網路連線失敗,此時再次重試是有機會連線成功並完成服務的;同時我們發現前面提到的網路服務生命週期處於1建立連線、序列化網路請求報文、傳送網路請求這三個階段失敗時,都是可以自動重試的,因為我們可以確信請求還沒有達到服務端進行處理,不會產生冪等性問題(如果存在冪等性問題,會出現重複訂單等情況)。當網路服務需要重試時,會使用短連線進行補償,而不再使用長連線。

實現了上述機制後,攜程App網路服務成功率由原先的95.3%+提升為如今的99.5%+(這裡的服務成功率是指端到端服務成功率,即客戶端採集的服務成功數除以請求總量計算的,並且不區分當前網路狀況),效果顯著。

6. 其他網路服務機制 & Tricks

攜程App也實現了其他一些網路服務機制方便業務開發,如網路服務優先順序機制,高優先順序服務優先使用長連線,低優先順序服務預設使用短連線;網路服務依賴機制,根據依賴關係自動發起或取消網路服務,例如主服務失敗時,子服務自動取消。

開發過程中我們也發現一些移動平臺上的TCP Socket開發tricks:

1) iOS平臺上的原生Socket介面建立連線並不會啟用行動網路,這裡原生Socket介面是指POSIX Socket介面,必須使用CFSocket或者再上層的網路介面嘗試網路連線時才會啟用網路。因此攜程App啟動時會優先啟用註冊一些第三方SDK以及傳送HTTP請求來啟用行動網路;

2) 合理設定Socket的幾個引數:SOKEEPALIVE引數確保TCP連線保持(注:此KeepAlive是TCP中的屬性,和HTTP的KeepAlive是兩個場景概念),SONOSIGPIPE引數關閉SIGPIPE事件,TCP_NODELAY引數關閉TCP Nagle演算法的影響;

3) 由於iOS要求支援IPv6-Only網路,因此使用原生Socket必須支援IPv6;

4) 如果使用select來處理nonblocking IO操作,確保正確處理不同的返回值和超時引數;

5) 保持TCP長連線可用性的心跳機制:對於非IM類應用而言,心跳機制的作用不大,因為使用者會不斷觸發請求去使用TCP連線,尤其在攜程業務場景下,通過資料統計發現使用心跳與否對服務耗時和成功率影響極小,因此目前已經關閉心跳機制。原先的心跳機制是TCP長連線池中的空閒TCP連線每60秒傳送一個心跳包到Gateway,Gateway返回一個心跳響應包,從而讓雙方確認TCP連線有效。

四、Hybrid網路服務優化

攜程App中有相當比例的業務是使用Hybrid技術實現的,執行在WebView環境中,其中的所有網路服務(HTTP請求)都是由系統控制的,我們無法掌控,也就無法進行優化,其端到端服務成功率也僅有97%左右(注:這裡指頁面中業務邏輯傳送的網路服務請求,而非靜態資源請求)。

我們採用了名為『TCP Tunnel for Hybrid』的技術方案來優化Hybrid網路服務,和傳統HTTP加速產品的方法不同,我們沒有采用攔截HTTP請求再轉發的方式,而是在攜程Hybrid框架中的網路服務層進行自動切換。

圖片描述

如圖所示,該技術方案的流程如下:

  1. 如果App支援TCP Tunnel for Hybrid,Hybrid業務在髮網路服務時,會通過Hybrid介面轉發至App Native層的TCP網路通訊層,該模組會封裝這個HTTP請求,作為TCP網路服務的Payload轉發到TCP Gateway;

  2. TCP Gateway會根據服務號判斷出是Hybrid轉發服務,解包後將Payload直接轉發至HTTP Gateway,此HTTP請求對HTTP Gateway是透明的,HTTP Gateway無需區分是App直接發來的還是TCP Gateway轉發來的HTTP請求;

  3. 後端業務服務處理完成後,HTTP響應會經HTTP Gateway返回給TCP Gateway,TCP Gateway將此HTTP響應作為Payload返回給App的TCP網路通訊層;

  4. TCP網路通訊層會再將該Payload反序列化後返回給Hybrid框架,最終非同步回撥給Hybrid業務呼叫方。整個過程對於Hybrid業務呼叫方也是透明的,它並不知道TCP Tunnel的存在。

採用該技術方案後,攜程App中Hybrid業務的網路服務成功率提升至99%以上,平均耗時下降了30%。

圖片描述

五、海外網路服務優化

攜程目前沒有部署海外IDC,海外使用者在使用App時需要訪問位於國內的IDC,服務平均耗時明顯高於國內使用者。我們採用了名為『TCP Bypass for Oversea』的技術方案來優化海外網路服務效能,主要是使用了Akaima的海外專屬網路通道,同時在攜程國內IDC部署了局端裝置,使用專用加速通道的方式來提升海外使用者體驗。

圖片描述

海外使用者啟動App後先通過Akaima定製域名獲取Server IP,所有網路服務優先走Akaima通道;如果Akaima通道的網路服務失敗並且重試機制生效時,會改走傳統Internet通道進行重試。相比只用傳統Internet通道,在保持網路服務成功率不變的情況下,使用Akaima通道Bypass技術後平均服務耗時下降了33%。

圖片描述

六、其他網路協議探討

過去兩年我們的網路服務優化工作都是基於TCP協議實現的,基本達到了優化目標。不過這兩年來新的應用層網路協議SPDY和HTTP/2逐步邁入主流,基於UDP的QUIC協議看起來也非常有趣,值得跟進調研。

SPDY & HTTP/2

SPDY是Google基於TCP開發的網路應用層協議,目前已經停止開發,轉向支援基於SPDY成果設計的HTTP/2協議,HTTP/2協議的核心改進其實就是針對HTTP/1.x中影響延遲效能的痛點進行優化:

  1. Header壓縮:壓縮冗餘的HTTP請求和響應Header;
  2. 支援Multiplexing:支援一個TCP連線上同時實現多個請求和響應。
  3. 保持長連線(比HTTP/1.x更徹底):減少網路連線時間。
  4. 支援推送:可以由服務端主動推送資料到客戶端。

官方效能測試結果顯示使用SPDY或者HTTP/2的頁面載入時間減少30%左右,不過這是針對網頁的測試結果,對於App中的網路服務,具體優化效果我們還在進行內部測試,不過其優化手段看和目前我們使用TCP協議的優化手段類似,因此效能優化效果可能不會很顯著。

QUIC

QUIC是Google基於UDP開發的應用層協議,UDP協議無需連線,不存在重傳機制,因此應用層需要保證服務的可靠性。目前國內騰訊有針對弱網路嘗試過QUIC協議,我們也在進行測試,最終是否會採用還需要看測試的結果。

七、綜述

技術只是手段,最終還是要反映在業務效果上。我們已經實現除靜態資源等需要訪問CDN的網路請求外,其他App網路服務使用統一的TCP通道,從而具備更好的效能調優和業務監控能力。

攜程目前基於TCP協議的各種App網路服務優化,也是各種技術方案的平衡,雖然目前HTTP/2等新協議逐步成熟,但是TCP協議自身的靈活性支援有針對性的效能優化,還是具備其特別的優勢,希望我們的實踐總結能對國內無線技術從業者有一些借鑑價值。

作者:陳浩然,攜程無線開發總監,計算機博士,2008年iOS SDK釋出後,投身移動網際網路。先後在外企、創業型和國內一線旅遊公司從事無線App的開發工作,從企業級App、獨立App到億級使用者量級的App都有全程參與。
責編:錢曙光,關注架構和演算法領域,尋求報導或者投稿請發郵件qianshg@csdn.net,另有「CSDN 高階架構師群」,內有諸多知名網際網路公司的大牛架構師,歡迎架構師加微信qshuguang2008申請入群,備註姓名+公司+職位。

相關文章