电竞比分网-中国电竞赛事及体育赛事平台

分享

HTTP、WebSocket、gRPC 或 WebRTC:哪種協(xié)議最適合您的應(yīng)用程序?

 邸彥強(qiáng) 2022-12-15 發(fā)布于河北
文章圖片1

在為您的應(yīng)用程序選擇通信協(xié)議時(shí),有很多不同的選擇。 本文將了解四種流行的解決方案:HTTP、WebSocket、gRPC 和 WebRTC。 我們將通過深入學(xué)習(xí)其背后原理、最佳用途及其優(yōu)缺點(diǎn)來探索每個(gè)協(xié)議。

通信方式在不斷改進(jìn):變得更快、更方便、更可靠,從使用信鴿發(fā)送信息,發(fā)展到郵政郵件,再到固定電話的發(fā)明,再到便攜式移動(dòng)設(shè)備。未來,甚至可能將會(huì)議和生日派對(duì)過渡到 VR(但愿這只是個(gè)玩笑?。?。

當(dāng)然,最好的溝通方式總是要視情況而定。快速的短信有時(shí)比長的電子郵件更好。 其他時(shí)候,與團(tuán)隊(duì)進(jìn)行視頻通話是交流信息的最佳方式, 相比之下,重要的保險(xiǎn)文件必須通過普通郵件發(fā)送并以紙質(zhì)形式交付。而使用的網(wǎng)絡(luò)技術(shù)和協(xié)議也是如此,不同的應(yīng)用程序有不同的通信需求。

1.概述

在本文中,我們將介紹一些可以作為開發(fā)人員使用的流行通信協(xié)議,并探討不同協(xié)議的優(yōu)缺點(diǎn)。 正如開頭所說,沒有比另一個(gè)更好的解決方案,只有一些解決方案更適合特定的應(yīng)用程序或問題。

一些應(yīng)用程序需要點(diǎn)對(duì)點(diǎn)連接,具有低延遲和高數(shù)據(jù)傳輸,并且可以接受一些數(shù)據(jù)包(信息)丟失。 有些應(yīng)用程序可以根據(jù)需要輪詢服務(wù)器,而不需要獲取被?輪詢方的同等數(shù)據(jù),有些應(yīng)用程序需要具有數(shù)據(jù)可靠性的實(shí)時(shí)通信,諸如此類。

在線多人游戲、消息傳遞應(yīng)用程序、博客網(wǎng)站、媒體庫應(yīng)用程序和視頻會(huì)議軟件都有不同的通信和數(shù)據(jù)需求。如果您正在構(gòu)建視頻流解決方案,那可能?還有其他注意事項(xiàng)。

2.什么是通信協(xié)議?

在計(jì)算機(jī)網(wǎng)絡(luò)中,協(xié)議是一組規(guī)則,用于管理數(shù)據(jù)在設(shè)備之間的交換方式。 該協(xié)議定義了通信的規(guī)則、語法、語義和同步以及可能的錯(cuò)誤恢復(fù)方法。本文中討論的協(xié)議定義了應(yīng)用層軟件如何相互交互。 不同的協(xié)議遵循不同的規(guī)則,了解每個(gè)協(xié)議的優(yōu)勢(shì)和局限性至關(guān)重要。

文章圖片2

不同協(xié)議的時(shí)間線

在本文中,您將了解以下協(xié)議:

  • HTTP(超文本傳輸協(xié)議):是分布式協(xié)作和超媒體信息系統(tǒng)的應(yīng)用協(xié)議。 HTTP 是萬維網(wǎng)數(shù)據(jù)通信的基礎(chǔ), 超文本是在包含文本的節(jié)點(diǎn)之間使用邏輯鏈接(超鏈接)的結(jié)構(gòu)化文本。 HTTP 是交換或傳輸超文本的協(xié)議。
  • HTTP/2: 旨在解決原始 HTTP 協(xié)議的缺點(diǎn)并提高性能。 HTTP/2 比 HTTP/1.1 更快、更高效,它支持多路復(fù)用,允許多個(gè)請(qǐng)求和響應(yīng)在單個(gè)連接上進(jìn)行多路復(fù)用。 其他值得注意的功能包括標(biāo)頭壓縮和服務(wù)器推送, 它正逐漸成為網(wǎng)絡(luò)流量的默認(rèn)協(xié)議。
  • WebSocket: 是一種允許客戶端和服務(wù)器之間進(jìn)行雙向通信的協(xié)議。 它是處理實(shí)時(shí)數(shù)據(jù)應(yīng)用程序的熱門選擇,例如聊天應(yīng)用程序、在線游戲和實(shí)時(shí)數(shù)據(jù)流。
  • gRPC :是一個(gè)使用 HTTP/2 進(jìn)行傳輸?shù)默F(xiàn)代開源 RPC 框架。 對(duì)于需要進(jìn)行大量小而快的 API 調(diào)用的應(yīng)用程序來說,這是一個(gè)很好的選擇。 gRPC 為多種語言生成跨平臺(tái)的客戶端和服務(wù)器綁定,使客戶端應(yīng)用程序可以直接調(diào)用不同機(jī)器上的服務(wù)器應(yīng)用程序的方法,就好像它是本地方法?一樣。
  • WebRTC: 是一種允許客戶端之間進(jìn)行實(shí)時(shí)通信,并使得建立直接對(duì)等連接成為可能的技術(shù)。 它用于視頻、聊天、文件共享和實(shí)時(shí)視頻流應(yīng)用程序。

3.了解 TCP 和 UDP

在深入研究上述應(yīng)用層之前,重要的是要對(duì) TCP 和 UDP 有一個(gè)基本的了解,這兩個(gè)底層傳輸層以根本不同的方式促進(jìn)數(shù)據(jù)傳輸。

  • TCP(傳輸控制協(xié)議):是定義如何通過 Internet 建立和維護(hù)網(wǎng)絡(luò)對(duì)話的標(biāo)準(zhǔn)。 TCP 是 Internet 和任何面向連接的網(wǎng)絡(luò)上最常用的協(xié)議。 當(dāng)您瀏覽網(wǎng)頁時(shí),您的計(jì)算機(jī)會(huì)向網(wǎng)絡(luò)服務(wù)器發(fā)送 TCP 數(shù)據(jù)包。 Web 服務(wù)器通過將 TCP 數(shù)據(jù)包發(fā)送回您的計(jì)算機(jī)來響應(yīng)。 在交換任何數(shù)據(jù)之前,首先在兩個(gè)設(shè)備之間建立連接,并且 TCP 使用糾錯(cuò)來確保所有數(shù)據(jù)包都成功傳遞。 如果數(shù)據(jù)包丟失或損壞,TCP 將嘗試重新發(fā)送它。
  • UDP(用戶數(shù)據(jù)報(bào)協(xié)議):是一種無連接、不可靠的傳輸層協(xié)議。 它不需要建立或維護(hù)連接,也不保證消息將按順序傳遞。 這意味著如果數(shù)據(jù)包未發(fā)送或損壞,可能會(huì)丟失一些數(shù)據(jù)。 UDP 通常用于流媒體或?qū)崟r(shí)應(yīng)用程序,在這些應(yīng)用程序中,丟失數(shù)據(jù)包的問題比確保交付要少。

4.HTTP/1

對(duì)應(yīng)用層所有基于互聯(lián)網(wǎng)的通信和數(shù)據(jù)傳輸?shù)幕A(chǔ)——HTTP(超文本傳輸協(xié)議)有一個(gè)基本的了解是很重要的。在更詳細(xì)地探索其他協(xié)議并充分理解它們提供的功能之前,了解 HTTP/1 及其局限性也很重要。

使用 HTTP,客戶端和服務(wù)器通過交換單獨(dú)的消息進(jìn)行通信。 客戶端發(fā)送的消息稱為請(qǐng)求,服務(wù)器發(fā)送的消息稱為響應(yīng)。 這些消息作為常規(guī)文本消息通過 TCP 連接發(fā)送。 它們也可以使用 TLS 加密并使用 HTTPS 協(xié)議發(fā)送。

客戶端通常是在用戶手機(jī)或計(jì)算機(jī)上運(yùn)行的 Web 瀏覽器或應(yīng)用程序,但從技術(shù)上講,它可以是任何東西,例如,抓取網(wǎng)站的腳本。HTTP 請(qǐng)求只能沿一個(gè)方向流動(dòng),即從客戶端到服務(wù)器。 服務(wù)器無法發(fā)起與客戶端的通信, 它只能響應(yīng)請(qǐng)求。

文章圖片3

HTTP/1.1傳輸示例

HTTP 非常適合傳統(tǒng)的 Web 和客戶端應(yīng)用程序,在這些應(yīng)用程序中,信息是按需獲取的。 例如,你刷新了一個(gè)頁面,向服務(wù)器發(fā)出了獲取最新信息的請(qǐng)求。

在接下來的部分中,我們將探討 HTTP/1 的一些限制。

4.1.HTTP/1 實(shí)時(shí)傳輸

當(dāng)消息需要從客戶端實(shí)時(shí)發(fā)送到服務(wù)器時(shí),HTTP/1 效率低下。 例如,如果服務(wù)器上有新信息需要與客戶端共享,則此事務(wù)只能在客戶端發(fā)起請(qǐng)求后發(fā)生。當(dāng)然,也有一些解決方法,例如?使用稱為 HTTP 短輪詢和長輪詢以及服務(wù)器發(fā)送事件的技術(shù)。

4.1.1 短輪詢

HTTP 短輪詢是一種客戶端重復(fù)向服務(wù)器發(fā)送請(qǐng)求直到它響應(yīng)新數(shù)據(jù)的技術(shù)。 一旦它接收到數(shù)據(jù),它就會(huì)再次啟動(dòng)該過程并反復(fù)詢問,直到有其他可用的數(shù)據(jù)?為止。

文章圖片4

HTTP短輪訓(xùn)

這是一種低效的實(shí)時(shí)通信策略,因?yàn)樗ㄟ^持續(xù)傳輸和解析 HTTP 請(qǐng)求/響應(yīng)浪費(fèi)了大量資源。

4.1.2 長輪詢

使用 HTTP 長輪詢,從客戶端發(fā)出單個(gè)請(qǐng)求,然后服務(wù)器保持該連接打開,直到有新數(shù)據(jù)可用并且可以發(fā)送響應(yīng)。 客戶端收到響應(yīng)后,立即再次建立新的連接。

文章圖片5

HTTP長輪詢

長輪詢比短輪詢更有效,但不是實(shí)時(shí)通信的最佳解決方案。

4.1.3 服務(wù)器發(fā)送的事件 (SSE)

服務(wù)器發(fā)送的事件允許客戶端保持打開的連接并實(shí)時(shí)從服務(wù)器接收推送消息,而不必不斷地輪詢服務(wù)器以獲取新數(shù)據(jù)。 這是一種單向連接,因此您無法將事件從客戶端發(fā)送到服務(wù)器。

SSE 是一種標(biāo)準(zhǔn),描述了一旦建立了初始客戶端連接,服務(wù)器如何啟動(dòng)向客戶端的數(shù)據(jù)傳輸。

4.2 HTTP/1 的性能問題

大多數(shù) HTTP 數(shù)據(jù)流由小的、密集?的數(shù)據(jù)傳輸組成,而 TCP 針對(duì)長期連接和批量數(shù)據(jù)傳輸進(jìn)行了優(yōu)化。 在大多數(shù)情況下,網(wǎng)絡(luò)往返時(shí)間是 TCP 吞吐量和性能的限制因素。 因此,延遲是性能瓶頸,大多數(shù) Web 應(yīng)用程序都可以克服它。

上面的意思是 HTTP 使用的 TCP 是為處理長期連接和傳輸大量數(shù)據(jù)而構(gòu)建的。 另一方面,HTTP/1 會(huì)打開一堆短暫的 TCP 連接,并且通常只發(fā)送小塊數(shù)據(jù)。

4.2.1 隊(duì)首阻塞

HTTP/1.0 的一個(gè)性能問題是您必須為每個(gè)請(qǐng)求/響應(yīng)打開一個(gè)新的 TCP 連接。 對(duì)于 HTTP 最初發(fā)明的目的而言(獲取超文本文檔),這不是問題。 文檔部分很重要,因?yàn)?HTTP 并不意味著“超媒體”。

隨著網(wǎng)絡(luò)的發(fā)展,為每個(gè)請(qǐng)求打開一個(gè)新的 TCP 連接成為一個(gè)問題。 我們開始構(gòu)建完整的應(yīng)用程序而不是簡單的網(wǎng)頁,瀏覽器需要檢索的媒體和文件的數(shù)量變得更多。 設(shè)想一個(gè)典型的 Web 應(yīng)用程序需要 HTML、CSS 和 JavaScript 文件,以及各種圖像和其他資產(chǎn)。 對(duì)于每個(gè)文件,都必須建立一個(gè)新的連接。

隨之而來的是 HTTP/1.1,它具有持久連接,它定義了可以在同一個(gè) TCP 連接上有多個(gè)請(qǐng)求或響應(yīng)。這個(gè)解決方案絕對(duì)是一個(gè)改進(jìn),但它不允許服務(wù)器同時(shí)返回多個(gè)響應(yīng)。 這是一個(gè)序列化協(xié)議,您必須在其中發(fā)送請(qǐng)求并等待響應(yīng),然后發(fā)送第二個(gè)請(qǐng)求,依此類推。 這稱為隊(duì)頭阻塞。

然而,實(shí)現(xiàn)某種并行性是可能的,因?yàn)闉g覽器最多可以打開六個(gè)(不同瀏覽器有差異)同一來源的 TCP 連接(其中“來源”被定義為主機(jī)和端口號(hào)的唯一組合)。

例如,如果您有一個(gè)需要加載 12 張圖像的照片庫應(yīng)用程序,那么將發(fā)出六個(gè)請(qǐng)求來加載前六張圖像,并且每個(gè)請(qǐng)求都會(huì)在后臺(tái)打開一個(gè)新的 TCP 連接。 其他六個(gè)圖像將被阻止,直到收到響應(yīng)并且打開的連接之一可用于加載下一個(gè)圖像。 最初的六個(gè)開放的同源 TCP 連接將在可用時(shí)被重用,但您僅限于六個(gè)活動(dòng)連接。

很自然地,程序員找到了一個(gè)簡單的解決方法——改變圖片源。 不是在同一個(gè)源上托管所有資產(chǎn),而是在一個(gè)源上托管六個(gè)圖像,其余的在另一個(gè)源上。 現(xiàn)在您可以有 12 個(gè)并發(fā)請(qǐng)求(或打開 TCP 連接),這被稱為“分片”。

  • 圖片 1–6 托管在 1.images.com 上
  • 圖片 7–12 托管在 2.images.com 上

但是,您可以執(zhí)行此操作的次數(shù)是有限制的,而且很難確定最佳的分片數(shù)量。 在某些時(shí)候,添加更多分片會(huì)增加復(fù)雜性、增加開銷,并可能導(dǎo)致鏈路擁塞和數(shù)據(jù)包丟失。

還有其他問題,因?yàn)槊總€(gè) TCP 連接都會(huì)給服務(wù)器增加不必要的開銷。 連接相互競爭,每次 TCP 和 TLS 握手都會(huì)增加不必要的成本,并且必須使用其他服務(wù)器/代理資源來維持活動(dòng)連接。 HTTP/1 使用底層 TCP 連接的方式有一個(gè)明顯的限制。

4.2.2 標(biāo)頭(Headers)和 Cookie 爆炸

另一個(gè)問題是,隨著 HTTP 規(guī)范的發(fā)展,規(guī)范中添加了更多的標(biāo)頭。 開發(fā)人員還可以選擇將 cookie 添加到標(biāo)頭,這些 cookie 可以任意大。 這增加了很多大小,因?yàn)槊總€(gè)請(qǐng)求和響應(yīng)都需要傳輸所有這些文本信息,并且 HTTP/1.1 不包含壓縮標(biāo)頭和元數(shù)據(jù)的機(jī)制。

如果您需要一個(gè)高性能的 RPC 協(xié)議,這種開銷會(huì)變得更大,此時(shí) HTTP 不再是最佳解決方案。

4.2.3 優(yōu)先級(jí)(Prioritization)

在 HTTP/1.1 中,瀏覽器通過在客戶端持有一個(gè)優(yōu)先級(jí)隊(duì)列來“確定”資源的優(yōu)先級(jí),并對(duì)如何充分利用可用的 TCP 連接進(jìn)行有根據(jù)的猜測(cè)。 瀏覽器嵌入了啟發(fā)式方法,用于確定哪些資源比其他資源更有價(jià)值。

例如,加載 CSS 將比加載圖像具有更高的優(yōu)先級(jí)。問題在于,作為開發(fā)人員,您無法確定一個(gè)請(qǐng)求的優(yōu)先級(jí)高于另一個(gè)請(qǐng)求或更改正在進(jìn)行的消息的優(yōu)先級(jí)。 首先加載什么內(nèi)容取決于瀏覽器,您對(duì)優(yōu)先級(jí)方案沒有發(fā)言權(quán)。

5.HTTP/2

5.1 HTTP/2 的優(yōu)點(diǎn)

HTTP/2 是 HTTP 協(xié)議的改進(jìn)版本,解決了上述 HTTP/1 的所有性能問題,并在不改變?nèi)魏握Z義(標(biāo)頭等)的情況下添加了其他增強(qiáng)功能。

HTTP/2 中最顯著的變化是使用多路復(fù)用。通過單個(gè) TCP 連接同時(shí)發(fā)送和接收多個(gè) HTTP 請(qǐng)求和響應(yīng)。 所有 HTTP/2 連接都是持久的,每個(gè)源只需要一個(gè)連接。 這允許更有效地使用網(wǎng)絡(luò)資源,并可以顯著提高應(yīng)用程序的性能。

HTTP/2 的其他一些好處:

  • 使用標(biāo)頭壓縮來減小標(biāo)頭的大小,從而避免一遍又一遍地發(fā)送相同的純文本標(biāo)頭。 這顯著減少了請(qǐng)求/響應(yīng)的開銷和發(fā)送的數(shù)據(jù)量。
  • 啟用優(yōu)先級(jí),允許客戶端(開發(fā)人員)指定其所需資源的優(yōu)先級(jí)。 也可以更新正在進(jìn)行的請(qǐng)求的優(yōu)先級(jí)——例如,在滾動(dòng)時(shí),如果圖像不再可見,則優(yōu)先級(jí)可以改變。
  • 使用服務(wù)器推送,在客戶端請(qǐng)求之前將數(shù)據(jù)發(fā)送到客戶端。 這可用于通過消除客戶端發(fā)出多個(gè)請(qǐng)求的需要來縮短加載時(shí)間。

5.2 HTTP/2 是如何工作的?

HTTP/2 中的基本協(xié)議單元是幀。 這種新的二進(jìn)制幀機(jī)制改變了客戶端和服務(wù)器之間的數(shù)據(jù)交換方式。

該標(biāo)準(zhǔn)定義了十種不同的幀類型,每種都有不同的用途。 例如,HEADERS 和 DATA 幀構(gòu)成了 HTTP 請(qǐng)求和響應(yīng)的基礎(chǔ):

文章圖片6

HTTP/1.1 vs HTTP/2

幀是承載特定類型數(shù)據(jù)的最小通信單位。 其他一些幀示例是:

  • 設(shè)置(SETTINGS):在開始或連接期間交換設(shè)置信息。
  • 優(yōu)先級(jí)(PRIORITY):重新分配消息的優(yōu)先級(jí)。
  • PUSH_PROMISE:允許服務(wù)器向您推送數(shù)據(jù),這是對(duì)服務(wù)器將發(fā)送的內(nèi)容的承諾。 例如,如果您請(qǐng)求 index.html,服務(wù)器可以創(chuàng)建一個(gè) PUSH_PROMISE 來承諾推送 app.js 和 styles.css,這意味著客戶端不需要主動(dòng)請(qǐng)求這些資源。

幀組合在一起形成消息,例如上圖中的標(biāo)題和數(shù)據(jù)幀。 這等同于正常的請(qǐng)求或響應(yīng)。最后,一系列消息可以成為流的一部分。 這允許客戶端和服務(wù)器之間的雙向數(shù)據(jù)流以及完整的請(qǐng)求和響應(yīng)多路復(fù)用。

文章圖片7

多路復(fù)用

上圖有點(diǎn)誤導(dǎo),給人的印象是客戶端和服務(wù)器之間打開了多個(gè)連接。但它是單個(gè) TCP 連接,數(shù)據(jù)以非阻塞方式在客戶端和服務(wù)器之間自由流動(dòng)。

文章圖片8

多路復(fù)用

新的二進(jìn)制框架層允許客戶端和服務(wù)器將 HTTP 消息分解為獨(dú)立的幀,組合發(fā)送,然后在另一端重新組合它們。這只是 HTTP/2.0 工作原理的總結(jié)。 如果您想了解更多信息并探索優(yōu)先級(jí)排序、服務(wù)器推送和標(biāo)頭壓縮,請(qǐng)參閱文末資料。

5.3 HTTP/2 雙向數(shù)據(jù)流

HTTP/2 規(guī)范表明:

“流”是在 HTTP/2 連接中客戶端和服務(wù)器之間交換的獨(dú)立地、雙向幀序列。

流有幾個(gè)重要的特征:

  • 單個(gè) HTTP/2 連接可以包含多個(gè)并發(fā)打開的流,其中任一端點(diǎn)交錯(cuò)來自多個(gè)流的幀。
  • 流可以單方面建立和使用,也可以由客戶端或服務(wù)器共享。
  • 流可以被任一端點(diǎn)關(guān)閉。

服務(wù)器推送功能存在很多誤解,它允許服務(wù)器通過 HTTP/2 主動(dòng)發(fā)送它認(rèn)為您可能需要的資源,例如 .js 和 .css 文件,而無需客戶端請(qǐng)求。 這與雙向流無關(guān),只是一種針對(duì)可緩存資源的 Web 優(yōu)化技術(shù)。

事實(shí)是,對(duì)于 HTTP/2 服務(wù)器無法啟動(dòng)流。 但是一旦客戶端通過發(fā)送請(qǐng)求打開一個(gè)流,雙方就可以隨時(shí)通過持久套接字發(fā)送數(shù)據(jù)幀。 一個(gè)很好的例子是 gRPC,我們將在后面討論。

使用 HTTP/2,可以實(shí)現(xiàn)雙向數(shù)據(jù)流,你可以爭辯說它是比 WebSockets 之類的東西更優(yōu)化的解決方案,或者你可以爭辯說它不是。 我們將在 WebSocket 部分更詳細(xì)地討論這個(gè)問題。

6.WebSockets

6.1 WebSockets 規(guī)范說明

來自 WebSocket 協(xié)議規(guī)范:

該技術(shù)的目標(biāo)是為基于瀏覽器的應(yīng)用程序提供一種機(jī)制,這些應(yīng)用程序需要與不依賴于打開多個(gè) HTTP 連接的服務(wù)器進(jìn)行雙向通信(例如,使用 XMLHttpRequest 或 iframe 和長輪詢)。

WebSockets 的發(fā)明是為了實(shí)現(xiàn)客戶端和服務(wù)器之間的全雙工通信,這允許數(shù)據(jù)立即通過單個(gè)打開的連接雙向傳輸。

建立 WebSocket 連接后,客戶端無需輪詢服務(wù)器以獲取更新。 相反,通信是雙向發(fā)生的。 與 HTTP/1 的原始長輪詢和短輪詢相比,這提高了速度和實(shí)時(shí)能力。 WebSocket 沒有特定要遵循的數(shù)據(jù)格式, 您可以使用它發(fā)送任何數(shù)據(jù)、文本或字節(jié),這種靈活性是 WebSockets 流行的原因之一。

其中一些內(nèi)容聽起來可能與我們?cè)?HTTP/2 部分中討論的內(nèi)容很熟悉,但重要的是要注意 WebSockets 是在 HTTP/2 之前很久就發(fā)明的。 稍后我們將對(duì)它們進(jìn)行更多比較。

6.2 WebSockets 如何工作?

WebSockets 底層基于 TCP 的傳輸層運(yùn)行。 要建立 WebSocket 連接,客戶端和服務(wù)器首先需要通過正常的 HTTP/1.1 連接執(zhí)行握手。此握手是從 HTTP 升級(jí)到 WebSockets 的橋梁。

文章圖片9

下面是一個(gè)示例客戶端握手請(qǐng)求??蛻舳丝梢允褂梅Q為升級(jí)標(biāo)頭的 HTTP/1.1 機(jī)制將其連接從 HTTP 切換到 WebSockets:

GET /chat HTTP/1.1Host: example.com:8000Upgrade: websocketConnection: UpgradeSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==Sec-WebSocket-Version: 13

然后服務(wù)器將用一個(gè)特殊的響應(yīng)結(jié)束握手,該響應(yīng)表明協(xié)議將從 HTTP 更改為 WebSocket:

HTTP/1.1 101 Switching ProtocolsUpgrade: websocketConnection: UpgradeSec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

WebSockets 需要具有 ws:// 或 wss:// 方案的統(tǒng)一資源標(biāo)識(shí)符 (URI)。 ws:// 方案用于未加密連接,wss:// 方案用于加密連接,類似于 HTTP URL 使用 http:// 或 https:// 方案的方式。

一旦建立了雙向通信通道,客戶端和服務(wù)器就可以來回發(fā)送消息。 這些消息可以是從二進(jìn)制數(shù)據(jù)到文本的任何內(nèi)容。 WebSocket 連接將保持打開狀態(tài),直到客戶端或服務(wù)器斷開連接。

6.3 WebSocket 多路復(fù)用

在撰寫本文時(shí),WebSocket 協(xié)議不支持內(nèi)置多路復(fù)用。 我們?cè)?HTTP/2 部分討論了多路復(fù)用,了解到它是 HTTP/2 的內(nèi)置功能,并且可以在同一連接上多路復(fù)用多個(gè)流。 每個(gè)流都有一個(gè)唯一的標(biāo)識(shí)符,所有發(fā)送的幀都有一個(gè)與相應(yīng)流關(guān)聯(lián)的 ID。

不支持多路復(fù)用意味著 WebSocket 協(xié)議需要為每個(gè) WebSocket 連接建立一個(gè)新的傳輸連接。 例如,在同一瀏覽器的不同選項(xiàng)卡中運(yùn)行的多個(gè)客戶端將使用單獨(dú)的連接。 要在 WebSockets 上進(jìn)行多路復(fù)用,您通常需要依賴第三方插件或庫。

6.4 WebSocket 與 HTTP/2

HTTP/2 取代了 WebSockets 了嗎? 答案是不!

HTTP/2 使雙向流成為可能,這使得 WebSockets 不是唯一/最佳選擇。 與 WebSockets 相比,HTTP/2 作為規(guī)范為您做了更多的工作。 它具有內(nèi)置的多路復(fù)用功能,在大多數(shù)情況下,將導(dǎo)致與源站建立的 TCP 連接更少。 另一方面,WebSockets 提供了很大的自由度,并且在建立連接后如何在客戶端和服務(wù)器之間發(fā)送數(shù)據(jù)方面沒有限制。 但是,您需要自己管理重新連接(或依賴為您執(zhí)行此操作的庫)。

至于那個(gè)更好,本文不給出答案,每個(gè)人有每個(gè)人的看法。WebSockets 提供了很大的靈活性,并且作為一個(gè)既定標(biāo)準(zhǔn),它得到所有現(xiàn)代瀏覽器的完全支持,并且圍繞客戶端和服務(wù)器庫的生態(tài)系統(tǒng)是強(qiáng)大的。有關(guān)更詳細(xì)和自以為是的討論,請(qǐng)參閱這些 Stack Overflow 問題:

  • HTTP/2 是否讓 WebSocket 過時(shí)了
  • 用于低延遲客戶端到服務(wù)器消息的 HTTP/2 或 Websockets
  • 用于雙向消息流的 HTTP/2 與網(wǎng)絡(luò)套接字

還有一個(gè) RFC 允許在 HTTP/2 連接的單個(gè)流上運(yùn)行 WebSocket 協(xié)議的機(jī)制。能夠從 HTTP/2 引導(dǎo) WebSockets ,即允許兩個(gè)協(xié)議共享一個(gè) TCP 連接,并將 HTTP/2 對(duì)網(wǎng)絡(luò)的更有效使用擴(kuò)展到 WebSockets。這已在 Chrome 和 Firefox 中實(shí)現(xiàn)。 您可以在此處閱讀 Chrome 設(shè)計(jì)文檔和動(dòng)機(jī)。

6.5 什么時(shí)候使用 WebSocket?

Websockets 最適合需要實(shí)時(shí)雙向通信的應(yīng)用程序,以及需要快速傳輸小塊數(shù)據(jù)的應(yīng)用程序:

  • 聊天應(yīng)用
  • 多人游戲
  • 協(xié)作編輯應(yīng)用程序
  • 直播體育賽事
  • 股票交易應(yīng)用
  • 實(shí)時(shí)活動(dòng)提要

對(duì)于服務(wù)器發(fā)送事件 (SSE), 在 HTTP/2 上非常高效且易于使用。 SSE 不是雙向通信系統(tǒng); 服務(wù)器單方面向客戶端推送數(shù)據(jù)。 但是,如果您所需要的只是服務(wù)器向客戶端發(fā)送數(shù)據(jù)的一種方式,那么這可能是比使用 WebSockets 更好的選擇。 當(dāng) HTTP/2 不可用時(shí),SSE 也會(huì)回退到 HTTP/1.1。 此外,客戶端(或?yàn)g覽器)為您管理連接并支持自動(dòng)重新連接。

如果通過 WebSockets 的連接丟失,則不包含用于負(fù)載平衡或重新連接的機(jī)制。 這必須手動(dòng)或由第三方庫實(shí)現(xiàn)。

6.gRPC

gRPC 是一個(gè)現(xiàn)代開源高性能遠(yuǎn)程過程調(diào)用 (RPC) 框架,可以在任何環(huán)境中運(yùn)行。 它可以通過對(duì)負(fù)載平衡、跟蹤、健康檢查和身份驗(yàn)證的可插拔支持,有效地連接數(shù)據(jù)中心內(nèi)和跨數(shù)據(jù)中心的服務(wù)。 它還適用于分布式計(jì)算的最后一英里,將設(shè)備、移動(dòng)應(yīng)用程序和瀏覽器連接到后端服務(wù)。

gRPC 是一個(gè)開源的、基于約定的 RPC 系統(tǒng),最初由谷歌開發(fā)。 gRPC 使應(yīng)用程序能夠透明地通信并簡化連接系統(tǒng)的構(gòu)建。它為多種語言生成跨平臺(tái)的客戶端和服務(wù)器綁定,使客戶端應(yīng)用程序可以直接調(diào)用不同機(jī)器上服務(wù)器應(yīng)用程序的方法,就好像它是本地對(duì)象一樣。

gRPC 基于 HTTP/2 構(gòu)建,利用雙向流和內(nèi)置傳輸層安全性 (TLS) 等功能。

6.1 gRPC 動(dòng)機(jī)

深入了解 gRPC 背后的動(dòng)機(jī)、發(fā)明它的原因以了解其好處非常重要。 為什么不使用我們已經(jīng)擁有的現(xiàn)有技術(shù):例如 HTTP/2 和 WebSockets? 為什么我們需要在已有的能力之上再抽象一層?

可以通過多種方式構(gòu)建數(shù)據(jù)并通過 Internet 發(fā)送數(shù)據(jù)。 一些流行的例子是 SOAP、REST 和 GraphQL。 您甚至可以創(chuàng)建自己的協(xié)議,通過原始 TCP 發(fā)送數(shù)據(jù),并根據(jù)需要自行處理實(shí)現(xiàn)。

但無論您選擇什么作為您的通信協(xié)議,問題在于您需要確??蛻舳撕头?wù)器就該協(xié)議達(dá)成一致。 例如,如果您正在構(gòu)建 REST API,則需要用于發(fā)送 REST 數(shù)據(jù)的客戶端庫是 HTTP 庫。 HTTP 庫默認(rèn)內(nèi)置于瀏覽器中,瀏覽器會(huì)為您處理一切:

  • 它與服務(wù)器建立通信。
  • 它處理 HTTP/2 并回退到 HTTP/1, 并且將來需要支持 HTTP/3。
  • 它處理 TLS 并協(xié)商協(xié)議。
  • 它處理標(biāo)頭、流和其他所有內(nèi)容。

但是,如果您不在瀏覽器上怎么辦? 如果您是在某個(gè)服務(wù)器上運(yùn)行的 Python 應(yīng)用程序、GoLang CLI 或在 iOS 上運(yùn)行的 Flutter 應(yīng)用程序怎么辦? 所有這些客戶端都需要自己的 HTTP 庫,該庫可以理解您正在與之通信的協(xié)議。

幸運(yùn)的是,許多人正在為所有這些語言和框架開發(fā)各種 HTTP 庫。 有些語言甚至有多個(gè)具有不同特性的 HTTP 庫。 然而,所有這一切都是有代價(jià)的,那就是維護(hù)。

如果您要將服務(wù)器升級(jí)到 HTTP/2(如果您使用的 GoLang 庫支持它),此成本可能會(huì)影響您。 但是,在您的前端 Python 客戶端上,等效的 HTTP 庫尚未實(shí)現(xiàn) HTTP/2,或者可能不再維護(hù)。

隨著 HTTP 規(guī)范的發(fā)展,這些庫必須同步更新,如安全問題、新功能等。 HTTP 只是一個(gè)例子,對(duì)于 WebSocket 協(xié)議或任何其他協(xié)議也是如此。 有些東西可能在主流瀏覽器中得到很好的實(shí)現(xiàn),但該功能必須移植到多種不同的語言和框架中。

6.2 gRPC 有何不同?

gRPC 試圖通過維護(hù)流行語言本身的庫來解決這個(gè)問題,這意味著所有這些語言都將支持添加的新功能。

gRPC 使用 HTTP/2 作為其協(xié)議,但是,這個(gè)實(shí)現(xiàn)對(duì)您是無感的。 將來,gRPC 的維護(hù)者可以輕松地將 HTTP/2 替換為 HTTP/3,您將立即從該更改中受益。

gRPC 還使用協(xié)議緩沖區(qū)作為接口定義語言 (IDL) 及其底層消息交換格式。 這種格式是語言中立的,可以輕松地在不同的編程語言之間進(jìn)行通信。 我們將在下一節(jié)中更多地探討這個(gè)概念。

文章圖片10

6.3 什么是協(xié)議緩沖區(qū)?

Protocol buffers 是 Google 設(shè)計(jì)的語言中立、平臺(tái)中立、可擴(kuò)展的結(jié)構(gòu)化數(shù)據(jù)序列化機(jī)制——想想 XML,但更小、更快、更簡單。 您一次性定義了數(shù)據(jù)的結(jié)構(gòu)方式。 然后,您可以使用特殊生成的源代碼輕松地將結(jié)構(gòu)化數(shù)據(jù)寫入各種數(shù)據(jù)流并使用各種語言從中讀取結(jié)構(gòu)化數(shù)據(jù)。

在 API 機(jī)制的設(shè)定中,您通常無需關(guān)心協(xié)議本身。 例如,如果您使用的是 REST,您通常只是發(fā)送帶有鍵/值對(duì)的 JSON 消息,直到消息到達(dá)接收端才進(jìn)行檢查。 此消息通??梢允侨魏蝺?nèi)容,由您來確保定義了正確的結(jié)構(gòu)。

查看以下 JSON 數(shù)據(jù)(payload):

{'id': 123,'name': 'Gordon','email': 'gordon@somewhere.io'}

在客戶端/服務(wù)器上接收到此數(shù)據(jù),就可以將其反序列化為一個(gè)對(duì)象,例如:

class Person {    int id;    String name;    String email}

但是,作為開發(fā)人員,您需要為上述數(shù)據(jù)實(shí)現(xiàn)正確的序列化和反序列化邏輯——這可能涉及手動(dòng)編寫 toJson 和 fromJson 方法,可以依賴于代碼生成,或者它可能是你正在使用的語言。

無論您如何序列化此數(shù)據(jù),底層代碼都需要手動(dòng)更新,可能在多個(gè)環(huán)境中,以防模式發(fā)生變化。而使用協(xié)議緩沖區(qū),您可以創(chuàng)建一個(gè)模式來定義字段的對(duì)象類型并指定哪些是必需的,哪些是可選的:

// The request message containing the person’s informationMessage Person { optional int32 id = 1; required string name = 2; optional string email = 3;}// The response message containing the greetingsmessage HelloReply { string message = 1;}

然后您可以指定對(duì)外的方法:

// The greeting service definition.service Greeter {  // Sends a greeting  rpc SayHello (Person) returns (HelloReply) {}}

一旦您指定了數(shù)據(jù)結(jié)構(gòu)和模式,您就可以使用協(xié)議緩沖區(qū)編譯器 將 protoc 從您的 proto 定義中,以您的首選語言生成數(shù)據(jù)訪問類。這些是描述 proto 文件中概述對(duì)象的接口,每個(gè)字段都有訪問器,以及將整個(gè)結(jié)構(gòu)序列化/解析為原始字節(jié)的方法。

6.4 gRPC 模式

gRPC 有四種傳輸方式, 這四種模式實(shí)現(xiàn)了之前討論的行為,例如,正常的請(qǐng)求/響應(yīng)、SSE 和 WebSockets。

6.4.1 一元 RPC

一元 RPC 是簡單的請(qǐng)求和響應(yīng),類似于調(diào)用函數(shù)。 客戶端請(qǐng)求一些數(shù)據(jù),服務(wù)器進(jìn)行一些處理并返回該數(shù)據(jù)。

6.4.2 服務(wù)器流式 RPC

服務(wù)器流式 RPC,其中客戶端向服務(wù)器發(fā)送單個(gè)請(qǐng)求并期望多個(gè)響應(yīng)或響應(yīng)流。 客戶端從返回的流中讀取,直到?jīng)]有更多消息為止。

一個(gè)例子是視頻流,您請(qǐng)求加載視頻,服務(wù)器響應(yīng)視頻流。

6.4.3 客戶端流式 RPC

客戶端流式 RPC,其中客戶端寫入一系列消息并將它們發(fā)送到服務(wù)器,再次使用提供的流。 客戶端完成消息寫入后,它會(huì)等待服務(wù)器讀取消息并返回響應(yīng)。

一個(gè)例子是將一個(gè)大文件上傳到服務(wù)器,一旦所有數(shù)據(jù)發(fā)送完畢,客戶端可以發(fā)送最終消息以指示上傳完成,并且服務(wù)器可以選擇響應(yīng)。

6.4.4 雙向流 RPC

客戶端和服務(wù)器流媒體的組合。 聊天應(yīng)用程序或多人視頻游戲是數(shù)據(jù)需要在客戶端和服務(wù)器之間自由流動(dòng)的示例。

雙向流式 RPC,雙方使用讀寫流發(fā)送一系列消息。 這兩個(gè)流獨(dú)立運(yùn)行,因此客戶端和服務(wù)器可以按照他們喜歡的任何順序進(jìn)行讀寫。

在雙向流式 RPC 中,調(diào)用由調(diào)用方法的客戶端發(fā)起。 客戶端和服務(wù)器端流處理是特定于應(yīng)用程序的。 由于兩個(gè)流是獨(dú)立的,因此客戶端和服務(wù)器可以按任意順序讀寫消息。

6.5 微服務(wù)

gRPC 強(qiáng)大之處的一個(gè)很好的例子是在微服務(wù)中。

文章圖片11

在這個(gè)例子中,我們有用 Python、Java 和 GoLang 編寫的微服務(wù),需要在它們之間發(fā)送數(shù)據(jù)。

使用 HTTP/1.1 和 JSON 將需要您為每種語言實(shí)現(xiàn) HTTP 連接和序列化。 您還需要確保為每種語言正確實(shí)施架構(gòu),如果 API 發(fā)生變化,則需要手動(dòng)更新所有服務(wù)。

另一方面,gRPC 為我們處理了 HTTP/2.0 協(xié)議的實(shí)現(xiàn)。 編寫單個(gè)模式,可以為所有使用的語言生成相應(yīng)的代碼。 這種模式可以看作是所有語言都需要遵守的契約,這使這些服務(wù)之間的通信更加容易和可靠。

6.6 gRPC 性能

gRPC 速度很快,通常比 REST 等價(jià)物的性能高得多:

  • 協(xié)議緩沖區(qū)被序列化并作為二進(jìn)制文件通過網(wǎng)絡(luò)發(fā)送,這比普通的 JSON 消息小得多。
  • gRPC 使用 HTTP/2.0 進(jìn)一步改進(jìn)

gRPC 有效壓縮發(fā)送的數(shù)據(jù)具有顯著優(yōu)勢(shì),因?yàn)閭鬏數(shù)臄?shù)據(jù)負(fù)載越小,需要的 TCP 往返次數(shù)就越少。 最大傳輸單元 (MTU) 是表示聯(lián)網(wǎng)設(shè)備將接受的最大數(shù)據(jù)包的大小,即 1,500 字節(jié)。

壓縮是自動(dòng)處理的,你只需使用 gRPC 就可以從中受益。 作為替代方案,可以在通過常規(guī) HTTP 發(fā)送之前使用 GZIP 之類的東西來壓縮 JSON 消息。 然而,這可能會(huì)帶來不便,并增加了一層復(fù)雜性。 不同的語言和環(huán)境也可能對(duì) GZIP 和其他等效壓縮工具有不同級(jí)別的支持。 對(duì)于您使用的每種語言,您都需要自己重新實(shí)現(xiàn)正確的壓縮和通信邏輯。 這與我們討論的有關(guān) HTTP 庫的問題類似。

6.7 什么時(shí)候應(yīng)該使用 gRPC?

如果您使用多種不同的編程語言,這些語言需要彼此緊密集成,并且需要快速頻繁地發(fā)送大量數(shù)據(jù)的通信,那么 gRPC 將是完美的選擇。

  • 優(yōu)點(diǎn):
    • 使用 gRPC 流式傳輸,可以輕松確定上傳/下載進(jìn)度,無需發(fā)出任何不必要的更新請(qǐng)求。
    • 可以取消請(qǐng)求。
    • HTTP/2 的所有優(yōu)點(diǎn)。
    • 如果 gRPC 支持你的語言,你就不必引入外部庫。
  • 缺點(diǎn):
    • gRPC 不支持所有語言。
    • 該架構(gòu)可能會(huì)讓人感到限制和麻煩。
    • 與 WebSockets 相比,它的設(shè)置可能很復(fù)雜。
    • 出現(xiàn)時(shí)間較晚,錯(cuò)誤可能難以調(diào)試。
    • 與 gRPC 的通信本身并不適用于 Web 瀏覽器, 您需要使用 gRPC-Web 庫。

7.WebRTC

7.1 WebRTC 特點(diǎn)

WebRTC 是一個(gè)免費(fèi)的開源項(xiàng)目,可為基于開放標(biāo)準(zhǔn)運(yùn)行的應(yīng)用程序提供實(shí)時(shí)通信 (RTC) 功能。 它支持在對(duì)等點(diǎn)之間發(fā)送視頻、語音和通用數(shù)據(jù)。

該技術(shù)作為一組適用于所有主流瀏覽器的 JavaScript API 和適用于 Android 和 iOS 應(yīng)用程序等本機(jī)客戶端的庫提供。

WebRTC根本上不同于 WebSockets 和 gRPC,一旦建立連接,數(shù)據(jù)就可以(在某些情況下)直接在瀏覽器和設(shè)備之間實(shí)時(shí)傳輸,而無需接觸服務(wù)器。

這減少了延遲并使 WebRTC 非常適合音頻、視頻或屏幕共享,低延遲并且可發(fā)送大量數(shù)據(jù)。

7.2 WebRTC 動(dòng)機(jī)

WebRTC 旨在標(biāo)準(zhǔn)化媒體(例如音頻和視頻)如何通過線路進(jìn)行通信,并通過簡單易用的 API 方便地實(shí)現(xiàn)這一目標(biāo)。

其他解決方案,例如 WebSockets,確實(shí)可以在兩個(gè)對(duì)等點(diǎn)之間傳輸任何數(shù)據(jù); 但是,此數(shù)據(jù)需要通過代理或服務(wù)器傳輸。 依賴另一臺(tái)服務(wù)器會(huì)增加延遲,因?yàn)橥ㄟ^它發(fā)送的所有內(nèi)容都需要接收、處理和解密。對(duì)于視頻流甚至實(shí)時(shí)聊天,這種延遲是不可取的。

現(xiàn)在的瀏覽器也比幾年前更強(qiáng)大。 瀏覽器可以訪問網(wǎng)絡(luò)攝像頭和麥克風(fēng),需要內(nèi)置 API 和一種簡單的方法來傳輸這些豐富的信息。 WebRTC 旨在簡化整個(gè)過程,并公開瀏覽器本機(jī)可用的,易于使用的 API。

7.3 WebRTC 問題

動(dòng)機(jī)已經(jīng)明確,WebRTC 似乎是一種神奇的解決方案,可以讓兩個(gè)對(duì)等方之間的通信更快。 但不幸的是,存在一些問題。

  • 第一個(gè)問題是建立點(diǎn)對(duì)點(diǎn)連接并不簡單,互聯(lián)網(wǎng)很復(fù)雜。加利福尼亞的 Alice 和南非的 Ben 之間有很多路由器、代理和防火墻。 在某些情況下,可能無法在兩個(gè)對(duì)等點(diǎn)之間建立直線。 兩個(gè)對(duì)等點(diǎn)之間的連接可能需要繞過阻止打開連接的防火墻,您可能沒有公共 IP 地址,或者路由器可能不允許對(duì)等點(diǎn)之間的直接連接。
  • 第二個(gè)問題是需要有一種方法讓兩個(gè)對(duì)等點(diǎn)相互發(fā)現(xiàn)并確定可以進(jìn)行通信的最佳路由。 這需要在兩個(gè)客戶端知道如何最好地相互通信之前在兩個(gè)客戶端之間共享某些信息,而共享此信息的一種常見方法是使用 WebSockets。

這有點(diǎn)好笑, 一個(gè) HTTP 連接升級(jí)為 WebSocket 連接只是為了共享建立 WebRTC 連接的信息。

如果您真的想了解 WebRTC 的功能及其復(fù)雜性,您需要熟悉一些可能不熟悉的術(shù)語:NAT、STUN、TURN、ICE、SDP 和信令。

7.4 WebRTC 是如何工作的?

在上面的概述中,我們描述了 WebRTC 的動(dòng)機(jī),本節(jié)將深入探討您需要了解的一些底層概念,以充分掌握 WebRTC。

7.4.1 網(wǎng)絡(luò)地址轉(zhuǎn)換 (NAT)

了解 NAT 是什么以及它如何工作對(duì)于理解 WebRTC 至關(guān)重要。NAT 用于為您的設(shè)備(筆記本電腦或手機(jī))提供公共 IP 地址; 這很重要,因?yàn)槲覀円诳赡芏荚诼酚善骱竺娴膬蓚€(gè)對(duì)等點(diǎn)之間建立連接。 路由器將有一個(gè)公共 IP 地址,連接到路由器的每個(gè)設(shè)備都將有一個(gè)私有 IP 地址。

這些設(shè)備不直接暴露在互聯(lián)網(wǎng)上。 相反,所有流量都通過與外界通信的路由器。 當(dāng)您從遠(yuǎn)程服務(wù)器請(qǐng)求資源時(shí),路由器負(fù)責(zé)將請(qǐng)求從本地計(jì)算機(jī)“路由”到該服務(wù)器,并將服務(wù)器的響應(yīng)路由回本地計(jì)算機(jī)。

這些請(qǐng)求從設(shè)備的私有 IP 地址轉(zhuǎn)換為具有唯一端口的路由器的公共 IP,然后存儲(chǔ)在 NAT 表中。 這樣,本地網(wǎng)絡(luò)上的每個(gè)設(shè)備都沒有必要擁有唯一的公共 IP。

文章圖片12

上圖是 NAT 表的簡單示例。 假設(shè)私有 IP 為 192.168.1.50 的本地設(shè)備請(qǐng)求公共地址 82.88.31.26:80 獲取一些數(shù)據(jù)。

這是通過本地設(shè)備首先向路由器發(fā)送請(qǐng)求,路由器將請(qǐng)求路由到遠(yuǎn)程設(shè)備來實(shí)現(xiàn)的。 路由器然后告訴遠(yuǎn)程設(shè)備將響應(yīng)發(fā)送到其外部 IP 地址,具有唯一端口,在本例中為 86.88.71.25:8830。

這個(gè)唯一的端口很重要,因?yàn)樗鼘⒃试S路由器確定發(fā)出請(qǐng)求的本地設(shè)備。 所有這些信息都存儲(chǔ)在 NAT 表中, 一旦路由器得到響應(yīng),它就可以執(zhí)行查找并決定將響應(yīng)轉(zhuǎn)發(fā)到哪個(gè)本地設(shè)備。

當(dāng)我們有一個(gè)正常的請(qǐng)求/響應(yīng)對(duì),即一個(gè)設(shè)備和一個(gè)服務(wù)器時(shí),這很容易理解。 但是,如果另一個(gè)具有完全不同 IP 地址的外部設(shè)備決定將數(shù)據(jù)包發(fā)送到先前使用的同一端口上的路由器外部 IP 地址,會(huì)發(fā)生什么情況? 路由器是否應(yīng)該將其轉(zhuǎn)發(fā)到映射到該端口號(hào)的本地設(shè)備?

該決定取決于路由器使用哪種 NAT 轉(zhuǎn)換,并最終確定是否可以建立對(duì)等連接。 根據(jù)您使用的路由器,它會(huì)執(zhí)行不同的 NAT 轉(zhuǎn)換。 有四種不同的 NAT 轉(zhuǎn)換方法:

  • 一對(duì)一 NAT
  • 將一個(gè)外部 IP 地址和端口(通常是公共的)映射到一個(gè)內(nèi)部 IP 地址和端口(通常是私有的)。 在上面的示例中,如果路由器在端口 8830 和外部 IP 86.88.71.25 上收到響應(yīng),它會(huì)將其轉(zhuǎn)發(fā)到本地設(shè)備 192.168.1.50,因?yàn)檫@是發(fā)出請(qǐng)求的本地設(shè)備(從 NAT 表中檢索的信息 ). 路由器不關(guān)心目標(biāo) IP 或響應(yīng)的來源。 如果它在特定的外部端口上,它將轉(zhuǎn)到該本地設(shè)備。
  • 地址限制 NAT
  • 僅當(dāng)本地設(shè)備先前已將數(shù)據(jù)包發(fā)送到遠(yuǎn)程 IP 地址時(shí),遠(yuǎn)程設(shè)備才能將數(shù)據(jù)包發(fā)送到本地設(shè)備。 總之,我們只有在之前與該主機(jī)通信過的情況下才允許它。 在上面的例子中,只允許來自 86.88.71.25 的數(shù)據(jù)包
  • 端口限制 NAT
  • 與地址限制 NAT 相同,但限制還包括端口號(hào)。 如果內(nèi)部設(shè)備先前已將數(shù)據(jù)包發(fā)送到 IP 地址 X 和端口 P,則遠(yuǎn)程設(shè)備只能將數(shù)據(jù)包發(fā)送到內(nèi)部設(shè)備。在上面的示例中,僅允許來自 86.88.71.25 和端口 80。
  • 對(duì)稱 NAT
  • 限制最嚴(yán)。 為此,外部 IP、外部端口、目標(biāo) IP 和目標(biāo)端口都必須與 NAT 表中的內(nèi)容相匹配。 這意味著數(shù)據(jù)包只能發(fā)送到本地設(shè)備的特定端口,前提是該設(shè)備是請(qǐng)求目標(biāo) IP 和端口的設(shè)備。

WebRTC 不能在對(duì)稱 NAT 上工作,要理解為什么我們需要理解什么是 STUN 服務(wù)器。

7.4.2 NAT 的會(huì)話遍歷實(shí)用程序 (STUN)

STUN 是一種協(xié)議,可通過 NAT 告訴您您的公共 IP 地址/端口,并確定您的路由器中會(huì)阻止與對(duì)等方直接連接的任何限制。 STUN 服務(wù)器是一種機(jī)制,供客戶端發(fā)現(xiàn) NAT 的存在以及 NAT 的類型,并確定 NAT 的外部 IP 地址和端口映射。

一個(gè) STUN 請(qǐng)求的目的是確定你的公開存在,這樣這個(gè)公開存在就可以與其他人交流,就可以與你聯(lián)系——這種交流被稱為信號(hào),我們將在后面詳細(xì)討論。

它適用于一對(duì)一、地址受限和端口受限的 NAT。 但不適用于對(duì)稱 NAT。 因?yàn)楫?dāng)您向 STUN 服務(wù)器請(qǐng)求您的公共信息時(shí),該通信對(duì)是專門為發(fā)出請(qǐng)求的客戶端創(chuàng)建的。 使用對(duì)稱 NAT 不可能涉及另一個(gè)對(duì)等點(diǎn)——通過本地設(shè)備端口的通信僅限于 STUN 服務(wù)器。

STUN 服務(wù)器重量輕,維護(hù)成本低。 有公共的 STUN 服務(wù)器可以免費(fèi)查詢。

下圖說明了 STUN 何時(shí)工作以及何時(shí)可以建立對(duì)等連接。

文章圖片13

另一方面,如果無法建立點(diǎn)對(duì)點(diǎn)連接,例如,當(dāng)對(duì)等點(diǎn)位于對(duì)稱 NAT 之后時(shí)——那么第三步中的最終連接將不會(huì)被允許。 由于初始連接是與 STUN 服務(wù)器建立的,沒有其他對(duì)等方可以使用該連接信息。在無法建立直接連接的情況下,我們需要使用 TURN 服務(wù)器。

7.4.3 使用中繼繞過 NAT 的遍歷(TURN)

TURN 是一種協(xié)議,用在無法在兩個(gè)對(duì)等點(diǎn)之間建立直接連接時(shí)中繼網(wǎng)絡(luò)流量。 例如,如果一個(gè)對(duì)等點(diǎn)位于對(duì)稱 NAT 之后,則需要一臺(tái)專用服務(wù)器來中繼對(duì)等點(diǎn)之間的流量。 在那種情況下,您將創(chuàng)建一個(gè)與 TURN 服務(wù)器的連接,并告訴所有對(duì)等方將數(shù)據(jù)包發(fā)送到該服務(wù)器,然后這些數(shù)據(jù)包將轉(zhuǎn)發(fā)給您。

這會(huì)帶來開銷,并且 TURN 服務(wù)器的維護(hù)和運(yùn)行成本可能很高。下圖說明了如何使用 TURN 服務(wù)器在兩個(gè)或多個(gè)對(duì)等點(diǎn)之間中繼消息。


文章圖片14

7.4.4 交互式連接建立(ICE)

ICE 使用 STUN 和 TURN 協(xié)議的組合,為主機(jī)提供一種機(jī)制來發(fā)現(xiàn)彼此的公共 IP 地址并建立直接連接。 如果無法直接連接,ICE 將使用 TURN 在兩臺(tái)主機(jī)之間建立中繼連接。

所有這些可能建立連接的可能方式都稱為 ICE 候選者。 所有收集到的地址都通過 SDP 發(fā)送到遠(yuǎn)程對(duì)等方,我們將在接下來進(jìn)行探討。 WebRTC 在每個(gè)客戶端上使用此信息來確定連接到另一個(gè)對(duì)等點(diǎn)的最佳方式。 可能是兩個(gè)對(duì)等點(diǎn)都在同一個(gè) NAT 上并且可以建立本地連接,或者可能是兩個(gè)對(duì)等點(diǎn)都在對(duì)稱 NAT 后面并且需要使用 TURN 服務(wù)器的中繼。

7.4.5 會(huì)話描述協(xié)議 (SDP)

SDP 本質(zhì)上是一種描述媒體會(huì)話的數(shù)據(jù)格式,用于會(huì)話公告、會(huì)話邀請(qǐng)和其他形式的會(huì)話發(fā)起。 它是描述連接的多媒體內(nèi)容的標(biāo)準(zhǔn),例如分辨率、格式、編解碼器和加密。

重要的是,它還用于描述 ICE 候選人和其他網(wǎng)絡(luò)選項(xiàng)。 當(dāng)對(duì)等點(diǎn) A 想要連接到對(duì)等點(diǎn) B 時(shí),他們需要共享 SDP 信息才能連接。 這個(gè) SDP 如何共享完全取決于——這被稱為信令,我們將在接下來探討它。

7.4.6 Signaling-建立連接

信令是在兩個(gè)設(shè)備之間發(fā)送控制信息以確定通信協(xié)議、信道、媒體編解碼器和格式、數(shù)據(jù)傳輸方法以及任何所需路由信息的過程。 關(guān)于 WebRTC 的信令過程,最重要的是要知道:它沒有在規(guī)范中定義。

對(duì)等連接處理連接不同計(jì)算機(jī)上的兩個(gè)應(yīng)用程序。 連接是通過稱為信令的發(fā)現(xiàn)和協(xié)商過程建立的。

一個(gè)重要的警告是 WebRTC 沒有內(nèi)置信號(hào)作為規(guī)范的一部分,因?yàn)閮蓚€(gè)設(shè)備不可能直接相互聯(lián)系,我們之前詳細(xì)探討過這一點(diǎn)。 對(duì)于使用 WebRTC 連接的兩個(gè)對(duì)等點(diǎn),它們需要彼此的 SDP 數(shù)據(jù)。

因此,作為開發(fā)人員,您有責(zé)任為兩個(gè)設(shè)備建立一種共享此信息的方式。 一個(gè)流行的選項(xiàng)是 WebSockets,或者可以通過電子郵件來回發(fā)送信令信息或步行傳遞并手動(dòng)輸入以建立連接。

一旦共享了此信息,您就擁有了兩個(gè)對(duì)等點(diǎn)建立 WebRTC 連接所需的一切,它可能是直接連接,也可能是通過 TURN 服務(wù)器。

7.5 什么時(shí)候應(yīng)該使用 WebRTC?

你甚至可能會(huì)問:我為什么要使用 WebRTC? 理解起來似乎很復(fù)雜,設(shè)置起來更復(fù)雜。但有很多好處:

  • API 易于使用,可直接在您的瀏覽器中使用。
  • 它具有良好的性能,可以傳輸高帶寬內(nèi)容,例如視頻或音頻。
  • 可以輕松實(shí)現(xiàn)更多高級(jí)功能,例如屏幕共享和文件共享。
  • 支持減少延遲的點(diǎn)對(duì)點(diǎn)連接。
  • 免費(fèi)和開源。

但是 WebRTC 也有缺點(diǎn):

  • 沒有內(nèi)置信號(hào)。
  • 您需要維護(hù) STUN 和 TURN 服務(wù)器。
  • 對(duì)于群組連接(例如群組視頻通話),可能需要 SFU。
  • 設(shè)置和理解起來很復(fù)雜。

8.HTTP、WebSockets、gRPC、WebRTC 如何選擇?

具體選擇哪個(gè)協(xié)議要視情況而定,沒有一個(gè)統(tǒng)一的答案,但是可以從宏觀上對(duì)比下幾種協(xié)議。

HTTP:使用 HTTP/2 可以在客戶端和服務(wù)器之間進(jìn)行雙向通信。 對(duì)于某些應(yīng)用程序,您可能不需要全雙工通信,像 SSE 這樣的東西就足夠了。 我們?cè)诒疚闹幸舶l(fā)現(xiàn) WebSockets 和 gRPC 依賴于 HTTP,而 WebRTC 也需要一些其他的信令通道。 在深入研究這些其他協(xié)議之前,值得首先探索 HTTP 是否能滿足您的實(shí)際需求。

WebSockets: 最適合需要雙向通信的實(shí)時(shí)應(yīng)用程序,例如聊天應(yīng)用程序, WebSockets 也相對(duì)容易設(shè)置和使用。 但是,WebSockets 的效率不如 gRPC 或 WebRTC,它們不太適合需要發(fā)送大量數(shù)據(jù)的應(yīng)用程序。

gRPC: 是一種比 WebSockets 更高效的協(xié)議,更適合需要發(fā)送大量數(shù)據(jù)的應(yīng)用程序。 但是,gRPC 的設(shè)置和使用比 WebSockets 更復(fù)雜。 如果你需要進(jìn)行很多小的 API 調(diào)用,gRPC 是一個(gè)不錯(cuò)的選擇。 或者,當(dāng)你用各種需要通信的編程語言實(shí)現(xiàn)微服務(wù)時(shí),那么 gRPC 的序列化結(jié)構(gòu)化數(shù)據(jù)和代碼生成會(huì)為你節(jié)省大量時(shí)間。 值得注意的是,您無法在瀏覽器端輕松使用 gRPC,當(dāng)然您可以手動(dòng)引入 grpc-web。

WebRTC: 是瀏覽器和設(shè)備之間低延遲實(shí)時(shí)通信的最有效協(xié)議,非常適合需要發(fā)送大量數(shù)據(jù)的應(yīng)用程序。 WebRTC 還提供了簡單易用的 API,可直接在瀏覽器中使用,從而輕松共享您的相機(jī)、音頻、屏幕或其他文件。 但是,WebRTC 的設(shè)置和使用可能很復(fù)雜,因?yàn)樗枰鷪?zhí)行信號(hào)發(fā)送,維護(hù) TURN 和 STUN 服務(wù)器。

9.結(jié)論

未來將會(huì)看到更多的協(xié)議、變化和進(jìn)一步的改進(jìn)。目前 HTTP/3 已經(jīng)發(fā)布,還有一個(gè)名為 WebTransport 的新通信協(xié)議,它有可能替代 WebSockets。

參考資料

https://github.com/grpc/grpc-web

https://v/webtransport/

https://levelup./http-websocket-grpc-or-webrtc-which-communication-protocol-is-best-for-your-app-1cc5a0786c86

https://v/performance-http2/

https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events

https:///agora-io/how-does-webrtc-work-996748603141

https:///blog/streaming-protocols/

https:///blog/peer-to-peer-video-conferencing/

https://www./rfc/rfc8441

https:///feature/6251293127475200

https://docs.google.com/document/d/1ZxaHz4j2BDMa1aI5CQHMjtFI3UxGT459pjYv4To9rFY/edit

https://zhuanlan.zhihu.com/p/421503695

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多