即將標準化的HTTP/3 協議雜談
HTTP/3協議即將標準化。作為一個老協議使用者,我想我該寫一些看法了。Google(pbuh)公司擁有最流行的web瀏覽器(Chrome)和兩個最流行的網站(#1 Google.com #2 Youtube.com)。因此谷歌可以控制web協議的發展。他們的第一次升級稱之為SPDY (發音”speedy”),這次更新最終成為HTTP協議第二版標準,即HTTP/2 。他們的第二次升級稱之為QUIC(發音”quick”),將成為HTTP/3協議標準。
SPDY (HTTP/2)已經得到了主流web瀏覽器(Chrome、Firefox、Edge、Safari)和主流web 服務器 (Apache、Nginx、IIS、CloudFlare)的支持。許多最流行的都支持它(即使是非google站點),儘管您不太可能在網上看到它(使用Wireshark或tcpdump進行嗅探),因為它總是使用SSL加密的。雖然標准允許HTTP/2在TCP上運行raw,但是所有實現都是SSL上使用它。
這裡有一個關於標準很好的一課。在互聯網之外,標准通常是法律上的,由政府管理,由所有主要利益相關者在一個房間裡討論,然後使用規則迫使人們採用它。在互聯網上,人們首先實現東西,然後如果其他人喜歡它,他們也會開始使用它。標准通常是事實上的,rfc是為已經在互聯網上運行良好的內容,記錄人們已經在使用的內容。瀏覽器/服務器採用SPDY並不是因為它是標準化的,而是因為主要的參與者只是簡單地開始添加它。同樣的情況也發生在QUIC上:它被標準化為HTTP/3的事實是它已經被使用,而不是人們可以開始使用它的標準化里程碑。
QUIC實際上更像是TCP (TCP/2???)的新版本,而不是HTTP (HTTP/3)的新版本。它並沒有真正改變HTTP/2的功能,而是改變了傳輸的工作方式。因此,我下面的評論集中在傳輸問題上,而不是HTTP問題。
主要的標題特性是更快的連接設置和延遲。TCP要求在建立連接之前來回發送大量數據包。SSL同樣需要在建立加密之前來回發送大量數據包。如果網絡延時很大,比如人們使用半秒ping時間的衛星互聯網,建立連接需要相當長的時間。通過減少往返,連接可以更快地建立,這樣當您單擊鏈接時,鏈接的資源就會立即彈出
下一個主要特性是帶寬。網絡連接的源和目的之間總是存在帶寬限制,這幾乎總是由於擁塞。雙方都需要使用這個速度,以便他們能夠以適當的速度發送數據包。如果發送數據包太快,那麼它們就會被丟棄,這會在不提高傳輸速率的情況下給其他數據包造成更大的擁塞。發送數據包太慢意味著不能最優地使用網絡。
HTTP傳統上這一點做得很糟糕。使用單個TCP連接不適用於HTTP,因為與網站的交互需要同時傳輸多個內容,因此瀏覽器打開了與Web服務器的多個連接(通常為6個)。但是,這會打破對帶寬的估計,因為每個TCP連接都嘗試獨立完成,就像其他連接不存在一樣。SPDY通過其多路復用功能解決了這個問題,該功能將瀏覽器/服務器之間的多個交互與單個帶寬計算相結合。
QUIC 擴展了這種多路復用,使得處理瀏覽器/服務器之間的多個交互變得更加容易,而沒有任何一個交互阻止另一個交互,且具有共同帶寬。從用戶的角度來看,這將使交互更加順暢,同時減少路由器遇到的擁塞。
我們現在來談談用戶模式棧。特別是在服務器上,TCP連接由操作系統內核處理,而服務本身在用戶模式中運行。跨內核/用戶模式邊界移動會導致性能降低。追踪大量TCP連接會導致擴展性問題。有些人嘗試將服務放入內核來避免轉換,這並不可取,因為它破壞了操作系統的穩定性。我的解決方案是用BlackICE IPS和masscan,使用自定義TCP棧,利用硬件的用戶模式驅動程序,將數據包從網絡芯片直接傳送到用戶模式進程,繞過內核(參見PoC || GTFO#15) 。近年來,DPDK套件已經變得流行。
但是,從TCP遷移到UDP可以在沒有用戶模式驅動程序的情況下獲得相同的性能。您可以調用recvmmsg()一次接收一堆UDP數據包,而不是調用眾所周知的recv()函數來一次接收一個數據包。它仍然是內核/用戶模式轉換,但是一次性收到的一百個數據包分攤,而不是每個數據包的轉換。
在我自己的測試中,使用典型的recv()函數限制為大約500,000 UDP數據包/秒,但使用recvmmsg()和其他一些優化(使用RSS的多核),可以在低端四核服務器上獲得5,000,000 UDP數據包/秒。由於每個核心的擴展性很好,因此遷移到具有64個核心的強大服務器可以進一步提高。
BTW,“RSS”是網絡硬件的一個特點,它將傳入的數據包分成多個接收隊列。多核擴展性的最大問題是兩個CPU核心需要同時讀取/修改同一個東西,因此共享相同的UDP隊列成為最大的瓶頸。因此,首先英特爾和其他以太網供應商添加了RSS,為每個核心提供了自己的非共享數據包隊列。Linux和其他操作系統升級UDP以支持單個套接字(SO_REUSEPORT)的多個文件描述符來處理多個隊列。現在,QUIC使用這些改進使得每個核心管理自己的UDP數據包流,不會有與其他CPU核心共享內容的導致可擴展性問題。之所以提到這一點,是因為在2000年,我親自與英特爾硬件工程師討論過有多個數據包隊列問題。這個問題很普遍,也有對應的解決方案,在HTTP / 3出現之前,看看在過去二十年中的發展也是很有意思。如果沒有網絡硬件中的RSS,QUIC就不太可能成為標準。
QUIC 的另一個優美的解決方案是對移動的支持。當你帶著你的筆記本電腦四處移動到不同的WIFI 網絡時,或者帶著你的手機四處移動時,你設備的IP 地址會發生變化的。操作系統以及協議不會優雅的關閉掉老的連接而打開新的連接。然而,QUIC,網絡連接的標識符並不是傳統概念上的一個“socket”(源/目標端口/地址協議的綁定),而是一個64位的賦值到連接上的標識符。
這意味著當你移動時,即使IP地址改變了,你依然能夠和YouTube繼續保持一個持續不間斷的流,或者繼續撥打一個視頻電話而不被異常中斷。網絡工程師們已經和“移動IP”的技術問題攻關了幾十年,試圖想出一個有效的解決方案。他們專注於端到端原則,也就是在你移動時以某種方式保持一個恆定的IP地址,這不是一個實際的解決方案。很高興看到QUIC / HTTP/3最終解決了這個問題。
如何使用這種新的交通工具?幾十年來,網絡編程的標準一直是被稱為“sockets”的傳輸層API。調用recv()之類的函數來接收代碼中的包。使用QUIC/HTTP/3,我們不再擁有操作系統傳輸層API。相反,它是一個更高層次的特性,可以在go編程語言中使用,或者在OpenResty nginx web服務器中使用Lua。
我之所以提到這一點,是因為在您對OSI模型的學習中,有一件事遺漏了,那就是它最初設想每個人都編寫應用層(7)api,而不是傳輸層(4)api。應該有一些應用程序服務元素,它們可以以標準的方式為不同的應用程序處理文件傳輸和消息傳遞之類的事情。我認為人們正越來越多地轉向這種模式,尤其是由帶有go、QUIC、protobufs等的谷歌驅動。
我之所以提到這一點,是因為谷歌和微軟之間的差異。微軟擁有一個流行的操作系統,所以它的創新是由它在該操作系統中所能做的事情驅動的。谷歌的創新是由它可以放在操作系統上的東西驅動的。然後是Facebook和亞馬遜自己,它們必須在谷歌提供的堆棧之上(或之外)進行創新。世界上排名前五的公司依次是蘋果、谷歌、微軟、亞馬遜和facebook,因此,每一家公司推動創新的地方都很重要。
結論
在20 世紀70 年代,TCP 被創造出來的時候,是非常了不起的。它處理的事情,如擁塞,比其他競爭性協議要好很多。人們沒有辦法預料到會有40 億個IPV4 地址的出現,那時候預計現代互聯網的競爭性設計會比七八十年代要好。
IPv4 到IPv6 的升級,很大程度上保持了IP 的優勢。從TCP 到QUIC 的升級同樣是基於TCP 的優點的,並將其擴展到現代需求上。實際上令人驚訝的是,TCP 已經持續瞭如此長的時間,它在沒有升級的情況下,做得很好。
原文鏈接: