文章來源於公衆號咖啡拿鐵 ,作者咖啡拿鐵
背景
又是一年一度的秋季校招開始了,以往的校招各個公司都會在公司現場或者學校現場安排學生進行現場面試?但是今年由於疫情的原因,不允許讓同學在現場進行一個面試,所以今年的面試形式就從線下轉到了線上,面試形式的轉變,但是我們考覈學生的方式依舊沒有轉變。
校招的同學和社招的同學有很大的不同,他們沒有豐富的工作經驗,沒有太多的項目經歷,那麼我們如何去衡量一個校招的同學呢?那就是基礎和潛力,怎麼去理解基礎呢?俗話說不積跬步,無以至千里,不積小流,無以成江海,如果沒有一個好的基礎那麼怎麼才能成爲一個優秀的工程師呢。如何去考察一個學生基礎的好壞呢?我覺得有三個方面比較重要,計算機網絡,操作系統以及算法和數據結構,通常來說計網考察得特別多,常見的一些問題:
網絡模型分層
TCP和UDP的區別
TCP三次握手和四次揮手
HTTP各版本的區別
上面列舉的問題只是其中一部分,這些問題基本在上課的書本中找到答案,如果你這些都不會那麼只能說基礎算是比較差了。由於這次是視頻面試,我通常會問你覺得牛客網的視頻面試是用的TCP還是UDP呢?在我揭曉答案之前大家也可以想想使用的是哪個網絡協議,在面試的過程中所有的同學都回答了應該是使用的是UDP。我問爲什麼使用UDP?基本都會回答道UDP是一個無連接的協議,不用保證可靠性,傳輸速度快。我又問道如果UDP不保證可靠性,咱們在視頻面試的時候我問你問題,如果你回答問題的視頻流丟包了,那麼你的答案我就聽不見了,那視頻面試的體驗將會非常低。不少同學在這個時候就會改答案說那應該使用的是TCP吧,我這是又會問道TCP由於需要保證可靠性,但是在公網的複雜環境下,想必應該經常會出現緩衝或者卡頓的現象吧,很多同學這個時候就會啞口無言了。
其實這個問題的答案不難想出,我們可以將TCP和UDP的特性互相結合起來,讓這個協議既可以保證可靠性,又可以保證實時性,這也就是我們所說的RUDP((Reliable UDP),常見的RUDP協議有QUIC,WebRTC,Aeron等等,我這裏主要介紹谷歌提出的QUIC,帶大家領略一下RUDP的精彩,看看他們是如何既能做到可靠又能保證效率。
QUIC
QUIC(Quick UDP Internet Connection)是Google公司提出的基於UDP的高效可靠協議,他和HTTP一樣同樣是應用層協議。
爲什麼高效呢?是因爲其基於無連接的UDP而不是基於TCP去實現的。
爲什麼可靠呢?因爲其模仿TCP協議的可靠性,在應用層上做了可靠性的保證。
爲什麼需要QUIC?
互聯網已經發展了幾十年了,但是一提到網絡協議,傳輸層使用得最多的還是TCP協議,應用層使用得最多的是HTTP協議,當然HTTP底層也是使用得TCP協議。雖然互聯網已經發展這麼久了但是對於TCP來說發展依舊緩慢,要說最大的改進應該是Google 在 ACM CoNEXT
會議上發表的用於改善 Web 應用響應延時TCP Fast Open,通過修改 TCP 協議利用三次握手時進行數據交換,這個在Linux內核 3.7.1 以及更高版本可以支持。由於修改TCP協議必然會修改內核從而導致系統升級,這個推動的難度非常之大。
既然我們修改內核不行,那麼Google就提出了在應用層協議上修改的辦法,也就有了QUIC。
誰在使用它?
首先使用它的人肯定是谷歌,據說谷歌有50%的請求都是QUIC協議,微博也在全面使用QUIC協議,同時還有一些視頻雲服務比如七牛也在使用,在騰訊內部也有很多部門在大量使用QUIC,所以不需要擔心這個協議使用的問題。
QUIC爲什麼這麼牛?
0RTT 建立鏈接
RTT((Round-Trip Time)顧名思義就是往返時延的意思,0RTT的話意思就是QUIC可以在第一次發送的時候就帶上數據,熟悉我們TCP的同學應該知道,TCP會有一個三次握手那麼實際上也就是會有1次RTT:
如果是HTTPS的話還會使用SSL/TLS的額外握手,就會有3次RTT:
那麼0RTT的建立鏈接QUIC是怎麼做到的呢?這裏得先說一下QUIC的0RTT並不是完全的0RTT,他同樣需要1RTT去做一次祕鑰協商,在QUIC中使用的是Diffie-Hellman密鑰交換,該算法是一種建立密鑰的方法,並非加密方法,但其產生的密鑰可用於加密、密鑰管理或任何其它的加密方式,這種密鑰交換技術的目的在於使兩個用戶間能安全地交換密鑰(KEY)以便用於今後的報文加密。DH算法用了離散對數的相關知識,這裏就不擴展講解,有興趣的可以下來搜索這種算法。QUIC通過DH算法創建一個安全的連接後,客戶端會緩存起來原始的連接信息等。在後續的過程中只要和同一個服務器建立鏈接都是直接發送數據,不需要再次協商祕鑰,從而實現了後續的0RTT。
更爲出色擁塞控制
TCP的擁塞控制的算法特別多,比如基於丟包反饋的(Tahoe、Reno、New Reno、SACK), 基於延時反饋的(Vegas、Westwood),其中的Reno也就是我們最爲熟悉的,它分爲四個階段:慢啓動,擁塞避免,快速重傳,快速恢復。
而在QUIC中使用了更爲優秀的機制來控制擁塞控制,它可以針對不同業務,不同網絡制式,甚至不同的RTT,使用不同的擁塞控制算法。同時也會採用了packet pacing來探測網絡帶寬,來提升網絡使用率。
更好的重傳機制
在重傳的機制中有一個比較重要的名詞,那就是RTO(Retransmission Timeout) 重傳超時時間,一般這個數據會根據RTT去進行計算,那麼我們有一個更精確的RTT肯定就可以有一個更好的RTO。
在TCP中重傳的時候序列號不變,會導致我們的RTT算得不準確,比如重傳的時候你不知道你這次請求到底是和原始請求匹配還是和重試請求匹配,就會導致我們的採樣RTT不準確。
在QUIC中序列號都是遞增的,並且通過offset來確定在包中的真實位置,這樣就可以得到更爲準確的RTT。
在TCP中計算RTT的方法就是發出的時間和響應回來的時間相減,但是這樣算出的時間不準確,在QUIC中會減去服務端Ack Delay的時間,這樣的話就更爲精準。
同樣的在TCP中有個SACK選項,該選項打開時用於記錄傳輸過程中一些沒有被確認的數據的範圍,便於後續定向重傳多組丟失數據,而不是全部重傳,所以更多的範圍便於更多的選擇重傳,也意味着更少的重傳包頻率。但TCP最多支持3個SACK範圍,而QUIC能支持255個。
沒有隊頭阻塞的多路複用
熟悉HTTP2.0的同學應該知道在2.0中如果訪問同一個服務器只會有一個TCP連接,所有的請求都會走這條連接:
而每個請求在Connection中叫做Stream,一個Connection中可以有多個Stream,這裏有個問題是在TCP中的包是保證時序的,如果某個Stream丟了一個包,他同時也會影響其他的Stream,在更爲嚴重的時候反而多路複用還不如HTTP1.1的多個鏈接。
而在QUIC中,因爲底層是基於UDP,UDP不需要保證包的時序,只會在接收包的時候對包進行重組,所以不會存在這個問題。這也就是爲什麼Google提議在HTTP3中使用QUIC的原因。
更優秀的流量控制
上面說了QUIC是多路複用的,在QUIC中可以針對Stream和Connection都進行流量控制。
QUIC 的流量控制和 TCP 有點區別,TCP 爲了保證可靠性,窗口左邊沿向右滑動時的長度取決於已經確認的字節數。如果中間出現丟包,就算接收到了更大序號的 Segment,窗口也無法超過這個序列號。
但 QUIC 不同,就算此前有些 packet 沒有接收到,它的滑動只取決於接收到的最大偏移字節數。
最重要的是我們可以進行動態配置,可以在內存不足或者上游處理性能出現問題時,通過流量控制來限制傳輸速率,保障服務可用性。
連接遷移
現在在手機上移動流量和wifi的切換是一個比較常見的事,每次切換ip地址都會發生變化,如果是TCP的話連接就會中斷從而進行重新建立鏈接。
在QUIC不再以 IP 及端口四元組標識,而是以一個 64 位的隨機數作爲 ID 來標識,通過這樣的方式可以進行連接重複利用,不會重新建立新的連接。
其他
在QUIC中還有更多的其他的特性,比如:
通過header stream保證流順序
底層保證連接持久
源地址令牌防止地址欺騙
握手時壓縮證書避免放大攻擊這裏就不一一介紹了
這裏就不詳解介紹了,大家可以自行查閱資料搜索。
總結
其實這篇帖子也算是一個掃盲貼,相信有很多朋友沒有聽說過RUDP相關的一些東西,或者說聽說過但是一直以爲他是一個很複雜,很難理解的東西,其實在這裏攤開來講RUDP就是一個UDP+應用層可靠協議組成的,希望大家看完這篇文章後,能有所收穫。
參考文章:
QUIC協議是如何做到0RTT加密傳輸的: https://blog.csdn.net/dog250/article/details/80935534
技術掃盲-新一代基於UDP的低延時網絡傳輸層協議——QUIC詳解 :http://www.52im.net/thread-1309-1-1.html
QUIC協議的分析,性能測試以及在QQ會員實踐:https://www.cnblogs.com/wetest/p/9022214.html
如果大家覺得這篇文章對你有幫助,你的關注和轉發是對我最大的支持,O(∩_∩)O: