傳輸體積下降 85%,融雲 HTTP 壓縮演算法解析

融雲RongCloud發表於2023-04-11

點選圖片報名社交泛娛樂出海賦能會【廣州站】

在音視訊通話,尤其是多人群組通話場景,過大的請求包體會導致客戶端頻繁報錯、連線超時等問題。關注【融雲全球網際網路通訊雲】瞭解更多

為解決這一問題,融雲引入並最佳化相關演算法,使呼叫和全域性雙向請求傳輸體積下降了 85%,為使用者提供更流暢的使用體驗。


業界主流壓縮演算法

HTTP(Hypertext Transfer Protocol,超文字傳輸協議)是一種請求/響應式的應用層協議。客戶端與伺服器建立連線後,向伺服器傳送一個請求;伺服器接到請求後,給予相應的響應資訊。

HTTP 包體主流壓縮演算法有 MiniSDP、Brotli、Gzip 等。

MiniSDP

在進行音視訊通話時,首先需要交換信令,SDP 互換就是其中的重要資訊,讓雙方瞭解彼此的音影片引數及能力。所以,包體中絕大部分是 SDP 內容,即專門用於描述多媒體資料的會話描述協議。

其主要內容包括會話所有者有關的引數、會話的起始時間和結束時間、傳送方所支援的媒體型別、媒體的連線資訊等,參與者人數越多,SDP 內容佔比越高。

因此,將 SDP 改造為 MiniSDP 一定程度上可以對 HTTP 包體進行壓縮。

WebRTC 的 SDP 用文字字串表示比較冗長,不利於快速高效傳輸;MiniSDP 把 SDP 文字壓縮成高效傳輸的二進位制流,具有高壓縮率、強擴充套件性、使用便利性。

mini_sdp 由 mini_sdp header、n 個 session 級別擴充套件和 n 個 media 三部分組成,具體結構如下:

mini_sdp header 主要定義 mini_sdp 傳輸所需要的一些輔助資訊及 ice 候選地址資訊,各欄位的長度及含義如下:

struct MiniSdpHdr {
    uint16_t version;           //2B, 表示該mini_sdp的版本號
    uint8_t is_bundle:1;        //1b, 0-未繫結, 1-繫結
    uint8_t plan_type:1;        //1b, 0-plan-b, 1-unifield-plan
    uint8_t dtls_role:2;        //2b, 0-actpass, 1-active, 2-passive
    uint8_t encrypt_switch:1;   //1b, 0-不加密, 1-encrypt_key加密
    uint8_t ip_type:1;          //1b, 0-ipv4, 1-ipv6
    uint8_t ice_type:1;         //1b, 0-full-lite, 1-ice-lite
    uint8_t reversed1:1;        //1b, 保留位
    uint8_t reversed2:5;        //5b, 保留位
    uint8_t candidate_num:3;    //3b, ice 候選地址的個數
    uint16_t media_num;         //2B, 原sdp中m行的個數
} __attribute__((packed));
注意:
1、version和media_num以網路位元組序傳輸;
2、必須支援ice,並且rtp和rtcp共用埠,否則會在media中增加ip,rtpPort,rtcpPort的開銷;
3、media_num用uint16_t,防止大會議使用unifield plan

struct MiniCandidateDesc {
  uint32_t ip[4];       //ipv4, ipv6轉換後的ip
  uint32_t priority;    //優先順序
  uint16_t port;        //埠
  uint8_t  type;        //0-host, 1-srflx, 2-prflx, 3-relay
} __attribute__((packed));
注意:priority和port以網路位元組序傳輸

session extenses 主要描述會話資訊:

{
    uint16_t ufrag_len;               //長度傳輸時使用網路位元組序
    const char* ice_ufrag;
    uint16_t pwd_len;
    const char* ice_pwd;
    uint16_t key_len;
    const char* encrypt_key;
    uint16_t session_id_len;
    const char* session_id;
    uint16_t session_version_len;
    const char* session_version;
}


session extenses 結構示意圖

struct MiniMediaHdr {
    uint8_t media_type:2;   //2b, 0-audio, 1-video, 2-data
    uint8_t codec_num:6;    //6b, 表示以下有多少個codec描述
    uint8_t direction:2;    //2b, 0-sendrecv, 1-recvonly, 2-sendonly, 3-inactive
    uint8_t rtcp_mux:1;     //1b, 0-不使能rtcp-mux, 1-使能rtcp-mux
    uint8_t reversed:5;     //5b, 保留  
    uint8_t rtp_extense_num;//1B, 表示以下有多少個rtp extense描述    
    uint16_t track_num;     //2B, 表示以下有多少個track描述    
} __attribute__((packed));
注意:track_num以網路位元組序傳輸

目前,客戶端和伺服器都不支援 MiniSDP,需要 SDP 與 MiniSDP 二者之間完成轉換。

經測試發現,原始 SDP 在 MiniSDP encode 和 decode 後,部分屬性會丟失或改變,還需對 MiniSDP 進行定製化開發支援。

資料主權

Brotli 是 Google 在 2015 年 9 月推出的一種壓縮演算法。它透過變種的 LZ77 演算法、Huffman 編碼及二階文字建模等方式進行資料壓縮,與其他壓縮演算法相比,Brotli 有著更高的壓縮效率。

根據 Google 釋出的研究報告,Brotli 壓縮演算法具有多個特點,最典型的是以下三個:

  • 針對常見的 Web 資源內容,Brotli 的效能相比 Gzip 提高了 17%-25%;
  • 當 Brotli 壓縮級別為 1 時,壓縮率比 Gzip 壓縮等級為 9(最高)時還要高;
  • 在處理不同 HTML 文件時,Brotli 依然能夠提供非常高的壓縮率。

Brotli 在壓縮程度上有著絕對的優勢,但是這些優勢是用其他代價換來的。Brotli 壓縮操作所花費的時間會隨著壓縮級別的增加而增加。

簡而言之,就是 Brotli 需要更多的計算能力,而計算能力需求的增加代表著裝置和軟體設施的成本上漲。另外,Brotli 要求瀏覽器必須支援與 HTTPS 一起使用,這也是它相比在瀏覽器支援量上比 Gzip 少的原因。

畢竟,Gzip 是同時支援 HTTP 和 HTTPS 的。

Gzip

Gzip 是 GNUzip 的縮寫,基於 DEFLATE 演算法實現,是 LZ77 和霍夫曼編碼的組合。

作為一種比較常用的資料壓縮方式,它最早用於 UNIX 系統的檔案壓縮。

HTTP 協議上的 Gzip 編碼是一種用來改進 Web 應用程式效能的技術,Web 伺服器和客戶端(瀏覽器)必須共同支援 Gzip。

目前,主流的瀏覽器如 Chrome、Firefox、IE 等和常見的伺服器如 Apache、Nginx、IIS 都支援該協議。

Gzip 常用於網站內容壓縮傳輸,以減少網路消耗,壓縮比率在 3 到 10 倍左右,可以大大節省伺服器的網路頻寬。

在實際應用中,它並不是對所有檔案進行壓縮,通常只壓縮靜態檔案。

服務中使用 Gzip 的方案示意如下:


各方案 PK 結果

資料壓縮傳輸的效率主要透過壓縮率和解壓縮時間來綜合判斷,三種方案的原始資料壓縮後資料大小如下:

實際包體長度 19678 的 Gzip 和 Brotli 壓縮比率與解壓縮時間對比如下:

在資料壓縮率上 Brotli > Gzip > MiniSDP,在解壓縮效率上 MiniSDP > Gzip > Brotli。

Gzip 壓縮在壓縮率上與 Brotli 相差不多,在各種瀏覽器中相容性更強,且解壓縮效率優於 Brotli。

綜合考慮相容性、開發量等因素,融雲選擇 Gzip 方案對呼叫和全域性雙向請求進行最佳化,使傳輸體積下降 85%,大大減少了傳輸效率問題和連線超時問題。

相關文章