你聽過HTTPS、HTTP2.0、SPDY,可是這些應用層協議都是基於可靠的傳輸層協議TCP來實現的。那麼,基於高效的UDP協議有沒有一種相對可靠的應用層協議呢?php
你聽過HTTPS、HTTP2.0、SPDY,可是這些應用層協議都是基於可靠的傳輸層協議TCP來實現的。那麼,基於高效的UDP協議有沒有一種相對可靠的應用層協議呢?html
圖1 why quic?nginx
What is QUIC?web
Quick UDP Internet Connection(QUIC)協議是Google公司提出的基於UDP的高效可靠協議。算法
說它高效,是由於使用了無鏈接的UDP而不是迭代週期更長的須要修改系統內核網絡棧的TCP協議。
說它可靠,是由於將改進了的可靠TCP的協議特徵用到了QUIC上。segmentfault
同時,也複用和改進了HTTP2的典型特徵,譬如二進制分幀,多路複用,header壓縮等。瀏覽器
圖2 what's quic?緩存
出於HTTP的明文和沒法驗證服務器的真實性,在TCP的基礎上引入了TLS協議,目前普遍使用的HTTPS是基於TCP+TLS協議,HTTP2也被主流瀏覽器默認支持TLS。安全
但對於創建鏈接的耗時而言,TCP自己就須要握手時延,而TLS協議爲了使得客戶端和服務器端在不安全的網絡通訊中協商出後續安全通訊所需的加密私鑰,更是要通過額外2次RTT(RoundTrip Time往返時間)服務器
圖3 TCP+TLS建連過程
除了TCP創建鏈接過程,TLS握手過程要通過以下步驟:
一、客戶端提供加密套件(算法)列表,版本等信息
二、服務器端提供本身的證書,選擇的加密套件,非對稱加密公鑰(本身保留私鑰)等
三、客戶端提供本身的證書,用服務器公鑰和加密套件加密的本身的私鑰
四、服務端用保留的私鑰解密客戶端傳來的加密私鑰,獲得的私鑰即爲後續加密傳輸使用的對稱密鑰,最後完成握手
此時,雙方協商出了對稱密鑰。基於TCP+TLS的HTTP2建連過程結束,大約須要耗時200-300ms。
爲了保證安全,QUIC也是加密傳輸數據的,因此在QUIC的建連過程當中也須要雙方協商出一個加密私鑰。但與TLS不一樣,QUIC採用的加密算法僅須要一個RTT就能實現密鑰交換,而且該算法也被用於目前正在草案階段的TLS1.3協議。該就是Diffie-Hellman密鑰交換算法。
圖4 Diffie-Hellman算法
能夠看到,客戶端和服務端各自保留了本身的私鑰a和b,經過交換各自的公鑰B和A,以及基底G和很大的質數P,雙方就能計算出相等的私鑰S,這個S就是加密傳輸的對稱密鑰。
另外,根據離散對數的不可逆,即便拿到G,P,和質數B,也很難推導出私鑰b(同理私鑰a),也就保證了計算密鑰的安全。
該過程對應到QUIC建連的過程當中以下圖。
圖5 1RTT建連
一、客戶端發起Inchoate client hello
二、服務器返回Rejection,包括密鑰交換算法的公鑰信息,算法信息,證書信息等被放到server config中傳給客戶端
三、客戶端發起client hello,包括客戶端公鑰信息
此時,雙方各自計算出了對稱密鑰。QUIC的1RTT建連過程結束,平均只耗時100ms之內。
後續發起鏈接的過程當中,一旦客戶端緩存或持久化了server config,就能夠複用並結合本地生成的私鑰進行加密數據傳輸了,不須要再次握手,從而實現0RTT創建鏈接。
協商升級
通常狀況下,Chrome瀏覽器和服務器端協商使用QUIC協議要通過以下步驟:
一、客戶端發出tcp請求
二、服務端若是支持quic能夠經過響應頭alt-svc告知客戶端
三、客戶端同時發起tcp鏈接和quic鏈接競賽
四、一旦quic創建鏈接獲勝則採用quic協議發送請求
五、如遇網絡或服務器不支持quic/udp,客戶端標記quic爲broken
六、傳輸中的請求經過tcp重發
七、5min後嘗試重試quic,下一次嘗試增大到10min
八、一旦再次成功採用quic並把broken標記取消
其中,支持quic的alt-svc頭部信息以下圖示,ma爲有效時間(單位秒),v爲支持的quic版本信息。
圖6 alt-svc頭信息
研究過程當中發現,除了alt-svc header,http2.0下服務端還能夠經過支持alt-svc frame來讓客戶端在第一次請求的時候就走新協議,比經過header讓瀏覽器第二次才能請求新協議更高效,這個留給後續研究。
鏈接遷移
TCP使用四元組(源IP,源端口,目的IP,目的端口)來標識一條鏈接,當四元組中的IP或端口任一個發生變化了鏈接就須要從新創建,從而不具有鏈接遷移的能力。
而QUIC使用了connection id對鏈接進行惟一標識。即便網絡從4G變成了wifi,只要兩次鏈接中的connection id不變,而且客戶端或者服務器能經過校驗,就不須要從新創建鏈接,鏈接遷移就能成功。
改進的多路複用
在SPDY協議出現之前,每一個HTTP請求都須要創建一條TCP鏈接,那麼若是但願請求並行,就須要同時開啓多條TCP鏈接(都是有建連代價的)。而大多數瀏覽器對於同一個域名能夠創建的最大TCP鏈接數是有限制的,因此,若是超出限制,更多的請求資源是沒法並行的。
SPDY協議以來提出的多路複用,是讓全部請求基於一條TCP鏈接,解決了上述的問題但同時引入了新的問題——隊頭阻塞,若是某個資源的某個包丟失了,由於TCP是保證時序的,就會在接收端造成隊頭阻塞,TCP此時沒法區分各個資源的包是否關聯,所以會中止處理全部資源直到丟包恢復。
圖7 基於TCP的多路複用
QUIC也有多路複用,可是QUIC是基於UDP的,UDP不須要保證包的時序,只會在接收包的時候對包進行重組,於是不存在等待丟包恢復的隊頭阻塞問題,這樣某個資源的包丟失只會影響自身不會影響到其餘資源的繼續傳輸,因此是改進的多路複用。
圖8 基於QUIC的多路複用
雙級別流量控制
QUIC是多路複用的,多條stream能夠創建在一條connection上,因此QUIC的流量控制不只基於單個stream,還基於connection。
stream級別的流控可以控制單stream的數據發送狀況。另外,接收窗口的收縮取決於最大接收字節的偏移而不是全部已接受字節的總和,它不像tcp流控,不會受到丟失數據的影響。
圖9 stream流控
若是知足(flow control receive offset - consumed bytes) < (max receive window / 2)
會觸發WINDOW_UPDATE frame的發送來增大發送窗口大小。
圖10 WINDOW_UPDATE觸發前
圖11 WINDOW_UPDATE觸發後
connection級別流控算法和stream一致,各項數值是全部stream的總和。
connection級別的流控存在的必要是,即便作好了stream流控,但若是stream過多也會致使connection過分消耗帶寬和系統資源;並且即便某一條stream過慢,其餘stream依然能觸發
connection級別的WINDOW_UPDATE,從而不會被影響。
圖12 connection流控
擁塞控制
咱們知道TCP有多種擁塞控制算法,當遇到網絡擁塞會經過減包等方式來避免網絡環境惡化。可是,UDP自己是沒有擁塞控制的,一旦不加約束的使用會致使侵佔其餘「守規矩」的網絡協議的帶寬。
因此,爲了不上述狀況,基於UDP的QUIC協議借鑑了TCP的一些優秀的擁塞控制算法,如默認使用Cubic,同時,爲了不AIMD機制帶來的帶寬利用率低,採用了packet pacing來探測網絡帶寬。
思路是,QUIC會經過追蹤包的到達時間來預測當前帶寬的使用狀況,以決定是否提升,保持或者減小發送包的速率來避免網絡擁塞。
圖13 packet pacing
丟包恢復
相似擁塞控制,除了基於TCP的一些丟包恢復機制,如:TLP,FACK。QUIC的丟包恢復也在一些方面作了改進。
好比:經過引入嚴格遞增的sequence number使得計算RTT更加精確。更精確的RTT也意味更精確的RTO和超時重傳機制。
還好比咱們知道TCP中有個SACK選項,該選項打開時用於記錄傳輸過程當中一些沒有被確認的數據的範圍,便於後續定向重傳多組丟失數據,而不是所有重傳,因此更多的範圍便於更多的選擇重傳,也意味着更少的重傳包頻率。但TCP最多支持3個SACK範圍,而QUIC能支持255個。
除了上述基於TCP的改進的丟包恢復特性之外,早期的QUIC版本還有一個丟包恢復機制,就是FEC(Forward Error Correction),這個特性雖然目前處於正在改造階段(可能會浪費帶寬而且做用不是很明顯),可是依然是一個有意思的解決方案。FEC的思路是經過在一組包(通常是10個)中,經過增長一個FEC包,並用FEC和每一個包進行XOR,若是一旦有丟包,那麼將FEC包和其他包XOR,獲得的FEC包就是那個丟包,因此一組包最多隻能恢復一個丟包。
更多特性
除了上述的主要特性,QUIC還有一些其餘特性,如:
● 經過header stream保證流順序
● 底層保證鏈接持久
● 源地址令牌防止地址欺騙
● 握手時壓縮證書避免放大攻擊
在此不深刻研究,你們有興趣能夠翻閱Google相關的文檔查閱。
業界應用狀況
● Google超過50%的請求來自QUIC
● 目前Youtube有20%的流量來自QUIC
● 微博移動端全面支持QUIC協議
測試demo
● 客戶端
最新版本PC Chrome(控制開啓/關閉quic)
● 服務器
經stgw改造支持quic的nginx
● 頁面地址(機器被回收,後續會更換機器供測試)
stgwquic.kof.qq.com/club/platfo…
stgwquic.kof.qq.com/club/platfo…
stgwquic.kof.qq.com/club/platfo…
● 網絡
公司staffwifi
● 抓包工具
wireshark
● 效果對比
圖15 HTTP1.1協議的頁面
圖16 HTTP2協議的頁面
圖17 QUIC協議的頁面
圖18頁面請求20個,大小2MB
圖 19 頁面請求15個,大小465KB
● 客戶端支持
X5內核團隊(移動端)
依賴用戶瀏覽器支持QUIC狀況(PC端)
● 服務端支持
STGW團隊
● 業務自身
按照路徑灰度,控制灰度策略
以上測試demo數據是基於公司良好的網絡狀況下測試獲得的,在實際運用過程當中,你們可能更關心在複雜的網絡環境下QUIC的表現。因而QQ會員團隊經過灰度現網的一個頁面來考察QUIC在現網的性能狀況。
● 頁面狀況
Android日PV100w,頁面大小95KB
總請求30個,其中主資源請求1個,CDN請求24個,其餘請求5個
展現部分依賴php直出和js渲染
● 灰度狀況
QUIC請求1個(php頁面主資源),HTTP2請求29個
● 灰度策略
客戶端天天放量,對比灰度過程當中頁面主資源的HTTP2和QUIC的性能數據
● 灰度效果
圖20 QQ會員頁面QUIC灰度狀況
● 效果說明
由於建連依賴於1RTT和0RTT機制,使得QUIC建連平均耗時僅需46ms,比HTTP2的225ms減小180ms左右。
因爲目前灰度量只佔到總請求量的10%,所以更嚴謹的性能對比數據有待進一步提升灰度範圍,以上僅做現階段參考。
但依然能夠看到QUIC在現網環境整體表現憂於HTTP2。
在實踐QUIC的過程當中,咱們也遇到了一些須要注意的問題。
● QUIC支持頭部alt-svc的緩存機制面向整個域名
業務即便只在一個頁面路徑下加了支持頭部(STGW能夠是路徑級別支持,X5只能是域名級別支持),瀏覽器也會根據頭部的緩存時長做用於用戶訪問該域名下的其餘頁面,但STGW可能只支持了路徑級別。因此灰度過程當中,儘可能使用有獨立域名的頁面。從而保證儘可能不影響其餘頁面的請求狀況(雖然QUIC請求失敗會降級H2),儘可能減小ma緩存時間。
● 客戶端對於QUIC的協商機制有待改善
在X5目前的實現機制中,不管如何首次請求都會基於HTTP2,後續纔會嘗試QUIC,但若是緩存時間設置的不夠長(譬如1天),會使得用戶通常1天內很難經過再次請求走到QUIC。因此,目前咱們作的是推進X5在請求時候讓白名單連接直接嘗試QUIC。同時,避免緩存時間隨着用戶退出手Q而失效,推進讓其落地。
● 目前客戶端基於X5的QUIC與一些基於緩存和預加載的頁面秒開方案衝突
若是大家的頁面是基於X5內核,可是使用了上述相似的技術,那麼存在一個問題是本來直接經過X5走QUIC協議的頁面不直接走X5了,而是基於你當前方案的緩存或者自定義的webview請求方式。因而經過統計數據會發現QUIC的請求量不多,由於上述技術目前還不支持QUIC協議。當前的作法是在QUIC和該方案中二選一。
● CDN請求灰度須要自支持
因爲CDN請求不基於STGW代理,於是須要CDN團隊針對業務方域名灰度支持,目前CDN總體處於運營商灰度QUIC階段。在此以前若是須要灰度CDN請求就須要業務方本身處理轉發。
● 運營商的Qos影響須要更完善的上報數據進行評估
使用QUIC協議比較擔憂的一個問題就是在網絡質量差的狀況下運行商Qos會對其產生怎樣的影響。從目前總體的統計數據,包括慢速用戶佔比等狀況來看,影響不是很大。後續須要推進各方完善上報監控該狀況下耗時。
● 和X5團隊一塊兒解決首次請求必走HTTP2請求問題
● 和X5團隊一塊兒解決alt-svc緩存有效期落地問題
● 和終端團隊一塊兒解決秒開方案下Webview對QUIC的支持,爭取既能使用QUIC協議又能使用秒開方案
● 配合CDN團隊驗證QUIC擴大灰度的支持效果
● 推進各方更細粒度的數據統計完善
參考資料
QUIC Crypto Adam Langley Wan-Teh Chang
fasterdata.es.net/host-tuning…
HTTP over UDP: an Experimental Investigation of QUIC
QUIC FEC v1 Author: ianswett@google.com Last Updated: 2016-02-19
Understanding QUIC wire protocol
IETF93 QUIC BarBoF: Congestion Control and Loss Recovery
QUIC: Performance and Security at the Transport Layer
WeTest壓測大師——爲了幫助開發者發現服務器端的性能瓶頸,騰訊WeTest開放了壓力測試功能,經過基於真實業務場景和用戶行爲進行壓力測試,實現針對性的性能調優,下降服務器採購和維護成本。
目前壓測大師服務了包括王者榮耀、QQ飛車手遊、QQ炫舞手遊等多款高星級手遊, 也服務了QQ、NOW直播、摩拜單車、企鵝FM等明星產品。
目前WeTest壓測大師對外開放中,點擊連接:wetest.qq.com/gaps 便可使用。
若是對使用當中有任何疑問,歡迎聯繫騰訊WeTest企業QQ:800024531