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竟然出问题了,说要重新加载,结果内容全没了。多么痛的领悟!只得收拾残碎的记忆又重新写了一遍。