Gzip通常指GNU计划实现的文件压缩程序,所以是GNUzip的缩写。在http协议中通过gzip来进行文件压缩,以减少资源在传输过程中所占用的带宽,提升网站性能,一般通过gzip压缩的文件只有原始大小的1/4,不过对于JPG/PNG 这类本身已经高度压缩的二进制文件,不建议使用内容压缩,效果微乎其微还浪费CPU。目前主流的浏览器,chrome、safari、firefox和IE都已经支持了gzip,常见的服务器如apache、Nginx、IIS也都支持了gzip,所以通过gzip进行文件压缩已经成为现在比较通用的资源传输方式。
通过上图我们可以清晰的看到在浏览器和服务端之间是如何使用gzip的:
需要注意的是压缩只针对传输正文,在http/1中,头部始终通过ASCII编码进行传输,没有经过任何压缩,不过在http/2中得到了解决,可以参考HTTP/2 头部压缩技术介绍
官方文档中对accept-encoding和content-encoding做了如下解释:
accept-encoding可以设置如下值:
gzip:是通过Lempel-Ziv coding(LZ77)压缩并使用32位循环冗余校验(CRC)的文件格式;
compress:是通过Lempel-Ziv-Welch(LZW)算法压缩的文件格式;
deflate:通过deflate压缩算法压缩,并使用zlib结构的文件格式,主要归咎于HTTP/1.1对deflate的错误命名导致这个地方含糊不清,应该理解为包含使用Lempel-Ziv压缩算法(LZ77)和哈夫曼编码的DEFLATE数据流的ZLIB数据格式;
br:使用Brotli算法压缩的文件格式;
indentity:设置一致性方法(例如:no compression、nor modification),默认值为acceptable,在这种情况下,就算客户端和服务端都支持同一种压缩方式,服务端也会因为一下原因而不压缩并直接返回:
;q=(weight):表明优先级,weight为权重;
常用库通过gzip压缩的效果:
|包名|原始大小|gzip压缩大小|压缩比| |-|-|-| |react15|23K|8K|34.8%| |react-dom15|130K|39K|30%| |react16|5K|2.6K|52%| |react-dom16|93K|29.4K|31.6%| |react-router|22K|7.2K|32.7%| |vue|87K|31K|35.6%| |preact|8K|3.7K|46.5%| |babel-polyfill|67K|18.5K|27.6%|
通过上面的介绍,如果要了解原理,首先得了解下面几个内容
LZ77与LZ78是Abraham Lempel与Jacob Ziv在1977年以及1978年发表的论文中的两个无损数据压缩算法。这两个算法是大多数LZ算法变体如LZW、LZSS以及其它一些压缩算法的基础。与最小冗余编码器或者进程长度编码器不同,这两个都是基于字典的编码器。 在了解LZ77原理之前,需要先了解几个概念:
现在我们来看一下压缩的具体过程:
gzip 中使用固定窗口大小,一般为32KB;
循环冗余校验是一种根据网络数据包或电脑文件等数据产生的简短固定位数校验码的一种散列函数,主要用来检验或校验数据传输或者保存后可能出现的错误。
先从最简单的奇偶校验说起吧,所谓奇偶校验就是在发送的每一个字节后面加上一位,使得每个字节中1的个数为基数或是偶数。奇偶校验的优点是非常简单,可以通过硬件实现,减少软件负担,但是缺点也是很明显的,它的错误检查率只有50%,而且每个字节都需要增加一位,对传输效率有影响。
累加和的校验方式有很多种,最常见的一种是在一次通讯包的最后加入一个字节的校验数据,这个字节内容为前面数据包中全部数据的忽略进位的按字节累加和。累加和方式也很简单,而且得到广泛应用,但是它的验错概率也比较一般。
终于到了重点CRC了,CRC的基本思想是将传输数据当做一个位数很长的数,将这个数除以另外一个数,得到的余数作为校验数据,附加到源数据后面。
在除法计算过程中遇到加减的情况,直接使用异或运算来取代,这样就不需要考虑借位问题,除法要更加简单一些,在除法计算中使用是除数有一个专有名词叫“生成多项式”,生成多项式对于错误的检查率至关重要,专家们经过多年研究,总结下面常用的生成多项式如下:
CRC8=X8+X5+X4+X0 CRC-CCITT=X16+X12+X5+X0 CRC16=X16+X15+X2+X0 CRC12=X12+X11+X3+X2+X0 CRC32=X32+X26+X23+X22+X16+X12+X11+X10+X8+X7+X5+X4+X2+X1+X0
需要注意的是:
gzip 中使用的是CRC-32;