使用QUIC
QUIC是Google新開發(fā)的一個基于UDP的協(xié)議,它提供了像TCP一樣的傳輸可靠性保證,可以實現(xiàn)數(shù)據(jù)傳輸?shù)?-RTT延遲,靈活的設(shè)計使我們可以對它的擁塞控制及流量控制做更多的定制,它還提供了傳輸?shù)陌踩员U?#xff0c;以及像HTTP/2一樣的應(yīng)用數(shù)據(jù)二進制分幀傳輸。
而QUIC協(xié)議最最吸引人的特性有兩點,一是對隊首阻塞問題的解決更為徹底。基于TCP的HTTP/2,盡管從邏輯上來說,不同的流之間相互獨立,不會相互影響,但在實際傳輸方面,數(shù)據(jù)還是要一幀一幀的發(fā)送和接收,一旦某一個流的數(shù)據(jù)有丟包,則同樣會阻塞在它之后傳輸?shù)钠渌c它毫不相干的流的數(shù)據(jù)的傳輸。而基于UDP的QUIC協(xié)議則可以更為徹底地解決這樣的問題,讓不同的流之間真正的實現(xiàn)相互獨立傳輸,互不干擾。
另一個特性切換網(wǎng)絡(luò)時的連接保持。當(dāng)前移動端的應(yīng)用環(huán)境,用戶的網(wǎng)絡(luò)可能會經(jīng)常切換,比如從辦公室或家里出門,WiFi斷開,網(wǎng)絡(luò)切換為3G或4G。基于TCP的協(xié)議,由于切換網(wǎng)絡(luò)之后,IP會改變,因而之前的連接不可能繼續(xù)保持。而基于UDP的QUIC協(xié)議,則可以內(nèi)建與TCP中不同的連接標(biāo)識方法,從而在網(wǎng)絡(luò)完成切換之后,恢復(fù)之前與服務(wù)器的連接。
由于這些良好的特性,QUIC協(xié)議已經(jīng)有在gmail中得到了大量的應(yīng)用。打開Wireshark,隨便對某個網(wǎng)卡抓包,都能看到大量的QUIC協(xié)議包:
這里我們來跑一下QUIC。
選擇一份QUIC代碼
下面的說明是用來基于chromium代碼庫編譯QUIC代碼。在Chrome支持的任何平臺上,這里的說明都能保證是有效的,遇到問題時可以查看一些擴展的故障排查的文檔。如果不想下載整個chromium代碼庫,則可以嘗試github上快速而干凈的proto-quic庫。這是chromium中的代碼的一份克隆,但剔除了大多數(shù)不必要的依賴,因而下載它要快得多,編譯也更快,但不一定在所有的平臺上都能用。事實上,github上的proto-quic庫,當(dāng)前只支持在Ubuntu linux上編譯。
編譯QUIC客戶端和服務(wù)器
Chromium中提供了一個示例客戶端和服務(wù)器實現(xiàn)。要使用這些東西,你首先應(yīng)該已經(jīng)下載Chromium的源代碼,然后構(gòu)建二進制文件:
ninja -C out/Debug quic_server quic_client這就像編譯chromium的任何模塊一樣。可以參考 懶人chromium net android移植指南 來對Chromium的構(gòu)建系統(tǒng)做更多了解。
如果條件允許,github上的proto-quic庫,編譯起來也很簡單快捷。首先需要下載代碼及構(gòu)建依賴的整個工具鏈:
git clone https://github.com/google/proto-quic.git cd proto-quic export PATH=$PATH:`pwd`/depot_tools ./proto_quic_tools/sync.sh然后編譯就是了,與普通的chromium模塊編譯一樣:
cd src gn gen out/Default && ninja -C out/Default quic_client quic_server net_unittests從www.example.org準(zhǔn)備測試數(shù)據(jù)
下載一份www.example.org的拷貝,它主要是給quic_server二進制可執(zhí)行文件用來提供本地服務(wù)的:
mkdir ~/quic-data cd ~/quic-data wget -p --save-headers https://www.example.org這里主要是要下載一個html文件,且保存文件的所有的HTTP header,當(dāng)然也可以從其它的站點下載這個文件。
手動地編輯index.html,并調(diào)整如下的headers:
- 移除(如果存在的話):"Transfer-Encoding: chunked"
- 移除(如果存在的話):"Alternate-Protocol: ..."
- 添加:X-Original-Url: https://www.example.org/
生成證書
為了運行服務(wù)器,需要一個有效的證書,及一個pkcs8格式的私有key。如果沒有,則可以使用腳本來產(chǎn)生它們:
cd net/tools/quic/certs ./generate-certs.sh cd -除了服務(wù)器的證書及public key,這個腳本也會產(chǎn)生一個CA證書 (net/tools/quic/certs/out/2048-sha256-root.pem),需要把它添加到操作系統(tǒng)的根證書商店以便于在證書驗證期間它被信任。
一種比較簡單的管理證書的方法是使用chrome瀏覽器。在地址欄中輸入 chrome://settings/search#ssl,然后點擊“管理證書”:
SSL Management
在彈出的窗口中選擇 “授權(quán)中心”,如下圖:
Import Certificate
然后點擊 “導(dǎo)入...” 按鈕,此時將彈出一個文件選擇對話框,我們選中所需要導(dǎo)入的根證書文件,也就是 net/tools/quic/certs/out/2048-sha256-root.pem,此時將有如下提示:
勾選其中的第一項,“信任該證書,以標(biāo)識網(wǎng)站的身份。”,然后點擊 “確定” 按鈕結(jié)束導(dǎo)入。
在linux上管理證書相關(guān)的更多信息,請參考 這些說明 。
如果遺漏了這里的添加CA證書的步驟的話,后面在執(zhí)行quic_client的時候會報出如下的證書驗證錯誤:
$ ./out/Default/quic_client --host=127.0.0.1 --port=80 https://www.example.org/ [1008/164047:ERROR:cert_verify_proc_nss.cc(942)] CERT_PKIXVerifyCert for www.example.org failed err=-8179 [1008/164047:WARNING:proof_verifier_chromium.cc(466)] Failed to verify certificate chain: net::ERR_CERT_AUTHORITY_INVALID Failed to connect to 127.0.0.1:80. Error: QUIC_PROOF_INVALID運行QUIC服務(wù)器和客戶端
運行quic_server:
./out/Default/quic_server \--quic_in_memory_cache_dir=~/quic-data/www.example.org \--certificate_file=net/tools/quic/certs/out/leaf_cert.pem \--key_file=net/tools/quic/certs/out/leaf_cert.pkcs8還可以通過--port參數(shù)指定quic_server監(jiān)聽的端口,及--v參數(shù)指定輸出更多信息,如:
./out/Default/quic_server --certificate_file=~/proto-quic/src/net/tools/quic/certs/out/leaf_cert.pem --key_file=~/proto-quic/src/net/tools/quic/certs/out/leaf_cert.pkcs8 --quic_in_memory_cache_dir=~/quic-data/www.example.com --port=32457 --v=1quic_in_memory_cache_dir參數(shù)指定存放資源文件的目錄路徑。如我們前面看到的,從www.example.org下載到頁面之后,需要調(diào)整headers,其中為X-Original-Url設(shè)置的是相應(yīng)資源的url。quic_server起來的時候,會加載該目錄下的文件。要為quic_server添加其它的測試資源,也要注意正確的設(shè)置其headers。如json接口:
# cat testApi1 HTTP/1.1 200 OK Cache-Control: private Content-Length: 3214 Content-Type: application/json; charset=utf-8 Server: Microsoft-IIS/7.5 X-AspNet-Version: 4.0.30319 X-Powered-By: ASP.NET Date: Thu, 13 Oct 2016 02:12:28 GMT X-Original-Url: https://www.wolfcstech.com:6121/testApi1{"res":[{"ctime":"2016-10-11","title":"溫州","des":"國內(nèi)","url":"http://news.163.com/16/1011/11/C33GFLIP0001124J.html"},{"ime":"2016","tit":"b","des":"a"}, {"ime":"2016","tit":"b","des":"a"}],"rea":"Su"}然后就可以使用quic_client以QUIC協(xié)議請求文件了:
./out/Default/quic_client --host=127.0.0.1 --port=32457 https://www.example.org/注意,如果要讓服務(wù)器運行于端口32457上,則必須為客戶端指定端口,因為它默認是80。
此外,如果本地機器有多個loopback地址 (由于它同時使用IPv4 和 IPv6),則不得不選定一個地址。
目前還不確定后面的缺點是不是一個bug。
注意:client和server都主要是為了做集成測試的:它們都不能大規(guī)模使用。
要使用chrome來測試相同的下載過程,可以執(zhí)行:
chromium-browser \--user-data-dir=/tmp/chrome-profile \--no-proxy-server \--enable-quic \--origin-to-force-quic-on=www.example.org:443 \--host-resolver-rules='MAP www.example.org:443 127.0.0.1:32457' \https://www.example.org使用Chromium net訪問QUIC資源
故障排查
如果你在運行時遇到了問題,則可以以--v=1參數(shù)運行服務(wù)器或客戶端。它將提升日志的verbosity,更多的日志常常可以幫助暴露底層的問題。
原文
超強干貨來襲 云風(fēng)專訪:近40年碼齡,通宵達旦的技術(shù)人生總結(jié)
- 上一篇: OkHttp3中的代理与路由
- 下一篇: Cronet android 设计与实现