传输体积下降 85%,融云 HTTP 压缩算法解析

2,137 阅读6分钟

640.png

点击图片报名社交泛娱乐出海赋能会【广州站】

在音视频通话,尤其是多人群组通话场景,过大的请求包体会导致客户端频繁报错、连接超时等问题。 关注【融云全球互联网通信云】了解更多

为解决这一问题,融云引入并优化相关算法,使呼叫和全局双向请求传输体积下降了 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 三部分组成,具体结构如下:

微信图片_20230404162313.png

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;
}

微信图片_20230404162320.png

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 二者之间完成转换。

微信图片_20230404162329.png

经测试发现,原始 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 的方案示意如下:

微信图片_20230404162334.png


各方案 PK 结果

数据压缩传输的效率主要通过压缩率和解压缩时间来综合判断,三种方案的原始数据压缩后数据大小如下:

原始数据长度32630(SDP:23725)8364(SDP:5559)
MiniSDP12911(8905+4006 MiniSDP 长度)3509(2805+704 MiniSDP 长度)
Brotli41001670
Gzip53191910

实际包体长度 19678 的 Gzip 和 Brotli 压缩比率与解压缩时间对比如下:

微信图片_20230404162340.png

在数据压缩率上 Brotli > Gzip > MiniSDP,在解压缩效率上 MiniSDP > Gzip > Brotli。

Gzip 压缩在压缩率上与 Brotli 相差不多,在各种浏览器中兼容性更强,且解压缩效率优于 Brotli。

综合考虑兼容性、开发量等因素,融云选择 Gzip 方案对呼叫和全局双向请求进行优化,使传输体积下降 85%,大大减少了传输效率问题和连接超时问题。