[轉] 攜程App網絡服務通道治理和性能優化@2016

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上實現服務路由、監控、反爬和用戶鑑權等功能。sql

每一個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應用層協議很難實現。ide

  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協議自身的靈活性支持有針對性的性能優化,仍是具有其特別的優點,但願咱們的實踐總結能對國內無線技術從業者有一些借鑑價值。

相關文章
相關標籤/搜索