在音视频通话,尤其是多人群组通话场景,过大的请求包体会导致客户端频繁报错、连接超时等问题。关注【融云全球互联网通信云】了解更多
为解决这一问题,融云引入并优化相关算法,使呼叫和全局双向请求传输体积下降了 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%,大大减少了传输效率问题和连接超时问题。