1、前言

gzip在*nix系统中是个压缩命令,用于把文件压缩成.gz后缀的文件,以减小磁盘占用空间。与之相对应的是命令gunzip,用于解压缩用gzip方法压缩的文件。nginx每天会对当天的访问日志进行压缩,通常在其日志文件目录下也可看到一大堆的access.log-yyyymmdd.gz文件。

nginx有个gzip模块,用于对输出到客户端的内容进行压缩,以减小传输文件体积,减少对网络带宽的占用。在Web应用中通常启用gzip压缩,用来缩短响应时间,提升用户体验。当然,服务器端要压缩,客户端必须解压缩,这都将占用cpu时间。不过,由于传输内容减小了,传输过程中,各网卡、路由器、交换机对数据包的处理时间也会缩短。gzip压缩是就在这里赢得了时间。

2、指令说明

gzip压缩功能要启用,必须满足以下几个条件:

  • 客户端发送的HTTP报头必须含有 “Accept-Encoding” 字段,且其值包含 “gzip” 这个压缩类型。一般浏览器都会发 “Accept-Encoding:gzip, deflate, sdch” 这样的报头。
  • 服务器做响应的配置,以nginx为例,示例配置如下:
# 对static目录下js、css、jpg、jpeg、png、gif后缀的文件启用gzip压缩功能
location ~ /static/(.+)\.(js|css|jpg|jpeg|png|gif) {
    gzip on; # 启用gzip压缩,默认是off,不启用
    # 对js、css、jpg、png、gif格式的文件启用gzip压缩功能
    gzip_types application/javascript text/css image/jpeg image/png image/gif;
    gzip_min_length 1024; # 所压缩文件的最小值,小于这个的不会压缩
    gzip_buffers 4 1k; # 设置压缩响应的缓冲块的大小和个数,默认是内存一个页的大小
    gzip_comp_level 1; # 压缩水平,默认1。取值范围1-9,取值越大压缩比率越大,但越耗cpu时间
}

如果服务器启用了gzip压缩,那么响应头会包含 Content-Encoding:gzip, 客户端根据这个来判断服务器返回的内容是否真正为gzip压缩过的内容。

3、对各文件的压缩比率测试

为方便对文件批量测试,写了个php小程序。

该程序处理的服务器返回的传输类型为分块传输,即带 “Transfer-Encoding:chunked” HTTP响应头。

function testGzip($host, $uri) {
    $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    socket_connect($socket, '127.0.0.1', 80);

    $request = "GET $uri HTTP/1.1\r\n";
    $request .= "Host: $host\r\n";
    $request .= "Accept-Encoding: gzip\r\n";
    $request .= "Connection: Keep-Alive\r\n\r\n";

    socket_write($socket, $request, strlen($request));

    $headers = [];
    while (($line = socket_read($socket, 1024, PHP_NORMAL_READ))) {
        socket_read($socket, 1, PHP_BINARY_READ);
        if ($line == "\r") {
            break;
        }
        $headers[] = rtrim($line, "\r");
    }

    $totalSize = 0;
    $chunkSizeList = [];
    $data = "";

    while (true) {
        $lenx = rtrim(socket_read($socket, 1024, PHP_NORMAL_READ), "\r");

        socket_read($socket, 1, PHP_BINARY_READ);
        $len =  hexdec($lenx);

        if ($len == 0) {
            socket_read($socket, 2, PHP_BINARY_READ);
            break;
        } else {
            //echo 'len=', $len, PHP_EOL;
        }

        $chunkSizeList[] = $len;
        $totalSize += $len;

        $data .= socket_read($socket, $len, PHP_BINARY_READ);
        socket_read($socket, 2, PHP_BINARY_READ);
        //usleep(10000);
    }

    socket_close($socket);

    $decodedData = gzdecode($data);
    #echo $decodedData;
    return [$headers, $chunkSizeList, $totalSize, strlen($decodedData)];
}

function batchGzipTest($host, $basePath, $files) {
    $stats = [];

    foreach ($files as $jsFile) {
        $stats[$jsFile] = testGzip($host, $basePath . $jsFile);
    }

    echo "|文件名|初始大小|压缩后大小|压缩比率|", PHP_EOL;
    echo "|------|:-----|:-----|:-----|", PHP_EOL;
    foreach($stats as $jsFile => $v) {
        echo "|", $jsFile, "|", $v[3], "|", $v[2], "|", sprintf("%.2f", ($v[3]-$v[2])/$v[3]*100), "%", "|", PHP_EOL;
    }
}

使用示例:

$host = 'invo.com';

$jsPath = '/static/js/';

$jsFiles = [
    'arttemplate.js', 
    'bootstrap.min.js', 
    'fastclick.min.js', 
    'jquery220.min.js', 
    'moment.min.js',
    'vue.js',
];

batchGzipTest($host, $jsPath, $jsFiles);
3.1 js文件压缩比率测试

对常用的6个js文件做了测试,结果如下:

文件名

初始大小

压缩后大小

压缩比率

arttemplate.js

4449

2257

49.27%

bootstrap.min.js

36868

11804

67.98%

fastclick.min.js

8776

3124

64.40%

jquery220.min.js

85589

34942

59.17%

moment.min.js

40737

15838

61.12%

vue.js

222777

75157

66.26%

最小49.27%,最大67.98%,还算不错!!

3.2 css文件压缩比率测试

对5个css文件进行测试:

文件名

初始大小

压缩后大小

压缩比率

bootstrap.min.css

121260

25198

79.22%

citheme.css

2486

1186

52.29%

datepicker3.css

33745

3867

88.54%

mui.min.css

77557

16183

79.13%

slider.css

8486

1745

79.44%

最小52.29%,最大88.64%,相当可以!!

3.3 图片文件压缩比率测试

3个png文件,2个jpg文件。

文件名

初始大小

压缩后大小

压缩比率

1.png

16953

16882

0.42%

2.png

117010

116875

0.12%

3.png

66492

62771

5.60%

4.jpg

775702

771901

0.49%

5.jpg

620888

618391

0.40%

没什么效果,令人失望!!估计是因为png、jpeg这些格式的图片已经是压缩过了的缘故。

3.4 html文件压缩比率测试

随机对5个html文件进行测试。

文件名

初始大小

压缩后大小

压缩比率

genindex.html

116025

17769

84.69%

index.html

53112

8726

83.57%

search.html

33589

6495

80.66%

license.html

35035

7285

79.21%

DCO.html

35168

7258

79.36%

效果比css文件的还要好!!

总结:gzip压缩对文本文件压缩效果非常好(40%~80%),而对图片文件效果甚微。实际应用中可以考虑对js、html、css格式的文件开启gzip压缩。估计json也是不错的,读者有兴趣可以自己去测试下。

4、后记

这篇文章快写完时,MarkDown竟然出问题了,说要重新加载,结果内容全没了。多么痛的领悟!只得收拾残碎的记忆又重新写了一遍。