小知识:Nginx服务器中使用gzip压缩的相关配置解析

gzip压缩

使用 gzip 压缩可以降低网站带宽消耗,同时提升访问速度。

主要在nginx服务端将页面进行压缩,然后在浏览器端进行解压和解析,

目前大多数流行的浏览器都迟滞gzip格式的压缩,所以不用担心。

默认情况下,Nginx的gzip压缩是关闭的,同时,Nginx默认只对text/html进行压缩

主要配置如下:
?
1
2
3
4
5
6
7
8
9
10
11
gzip on;#开启
gzip_http_version 1.0;#默认1.1
gzip_vary on;
gzip_comp_level 6;
gzip_proxied any;
gzip_types text/plain text/html text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;#压缩的文件类型
gzip_buffers 16 8k;#设置gzip申请内存的大小,其作用是按块大小的倍数申请内存空间设置gzip申请内存的大小,其作用是按块大小的倍数申请内存空间
# Disable gzip for certain browsers.
gzip_disable “MSIE [1-6].(?!.*SV1)”;#ie6不支持gzip,需要禁用掉ie6,可恶啊!!!!

注意: 其中的gzip_http_version的设置,它的默认值是1.1,就是说对HTTP/1.1协议的请求才会进行gzip压缩

如果我们使用了proxy_pass进行反向代理,那么nginx和后端的upstream server之间是用HTTP/1.0协议通信的。

gzip参数说明:

决定是否开启gzip模块

param:on|off

example:gzip on;

gzip_buffers

设置gzip申请内存的大小,其作用是按块大小的倍数申请内存空间

param1:int 增加的倍数

param2:int(k) 后面单位是k

example: gzip_buffers 4 8k;

gzip_comp_level

设置gzip压缩等级,等级越底压缩速度越快文件压缩比越小,反之速度越慢文件压缩比越大

param:1-9

example:gzip_com_level 1;

gzip_min_length

当返回内容大于此值时才会使用gzip进行压缩,以K为单位,当值为0时,所有页面都进行压缩

param:int

example:gzip_min_length 1000;

gzip_http_version

用于识别http协议的版本,早期的浏览器不支持gzip压缩,用户会看到乱码,所以为了支持前期版本加了此选项,目前此项基本可以忽略

param: 1.0|1.1

example:gzip_http_version 1.0

gzip_proxied

Nginx做为反向代理的时候启用,

param:off|expired|no-cache|no-sotre|private|no_last_modified|no_etag|auth|any]

expample:gzip_proxied no-cache;

off – 关闭所有的代理结果数据压缩

expired – 启用压缩,如果header中包含”Expires”头信息

no-cache – 启用压缩,如果header中包含”Cache-Control:no-cache”头信息

no-store – 启用压缩,如果header中包含”Cache-Control:no-store”头信息

private – 启用压缩,如果header中包含”Cache-Control:private”头信息

no_last_modified – 启用压缩,如果header中包含”Last_Modified”头信息

no_etag – 启用压缩,如果header中包含“ETag”头信息

auth – 启用压缩,如果header中包含“Authorization”头信息

any – 无条件压缩所有结果数据

gzip_types

设置需要压缩的MIME类型,非设置值不进行压缩

param:text/html|application/x-javascript|text/css|application/xml

example:gzip_types text/html;

gzip_vary on;

和http头有关系,加个vary头,给代理服务器用的,有的浏览器支持压缩,有的不支持,所以避免浪费不支持的也压缩,所以根据客户端的HTTP头来判断,是否需要压缩

Nginx与Gzip请求

一般线程的Nginx的Gzip模块都是和Response相关的Gzip,但如果需要的是和Request相关的Gzip呢?来看下面:

方案

第一个选择是使用lua-zlib:

?
1
2
3
4
5
6
7
8
9
10
11
12
local zlib = require “zlib”
local encoding = ngx.req.get_headers()[“Content-Encoding”]
if encoding == “gzip” then
local body = ngx.req.get_body_data()
if body then
local stream = zlib.inflate()
ngx.req.set_body_data(stream(body))
end
end

第二个选择是通过LuaJIT的FFI库来包装ZLIB模块,官方教程里有一些现成的可供参考的的例子,不过例子里介绍的是Deflate,而不是Gzip,自己用FFI封装Gzip的话又有点小复杂,好在别人已经做了相关的工作,那就是lua-files:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
local ffi = require “ffi”
local zlib = require “zlib”
local function reader(s)
local done
return function()
if done then return end
done = true
return s
end
end
local function writer()
local t = {}
return function(data, sz)
if not data then return table.concat(t) end
t[#t + 1] = ffi.string(data, sz)
end
end
local encoding = ngx.req.get_headers()[“Content-Encoding”]
if encoding == “gzip” then
local body = ngx.req.get_body_data()
if body then
local write = writer()
zlib.inflate(reader(body), write, nil, “gzip”)
ngx.req.set_body_data(write())
end
end

如上例子代码源自zlib_test.lua,乍看上去,代码里的reader和writer可能会令人费解,其实你可以把它们理解成输入输出接口,可以修改成文件,数据库等等形式。

别高兴太早,当你运行时,很可能会遇到如下错误:

?
1
libzlib.so: cannot open shared object file.

实际上这是因为如下zlib.lua代码的缘故:

?
1
local C = ffi.load zlib

运行时,ffi.load会自动补全文件名,如果是Windows,则加载zlib.dll文件,如果是Linux,则加载libzlib.so,但实际上在Linux下,ZLIB扩展的名字是libz.so,而非libzlib.so。

知道的问题的原委,我们自然就知道如何修改代码了:

?
1
2
3
4
5
6
7
local C
if ffi.os == “Windows” then
C = ffi.load “zlib”
else
C = ffi.load “z”
end

有时候我们不推荐直接修改第三方库的代码,因为这样的话,每次第三库更新代码,我们都要做对应的修改,一旦忘记就会出错,这时候可以考虑做一个软连接别名。

测试

开篇说过,接口都是用PHP做的,不过请求里的Gzip数据是用LUA处理的,如何让PHP使用LUA处理后的数据呢?不同的语言似乎是个难题,好在Nginx有Phases一说,PHP作为FastCGI模块工作在content阶段,LUA可以工作在access阶段,这样它们就和谐了:

?
1
2
3
4
5
6
location ~ \.php$ {
access_by_lua_file /path/to/lua/file;
include fastcgi.conf;
fastcgi_pass 127.0.0.1:9000;
}

那么lua-zlib和lua-files两种方案效率如何?下面是我用PHP写的测试脚本:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php
$url = http://url;
$header = implode(“\r\n”, array(
Content-Type: application/x-www-form-urlencoded,
Content-Encoding: gzip,
Connection: close,
));
$content = gzencode(http_build_query(array(
foo => str_repeat(x, 100),
bar => str_repeat(y, 100),
)));
$options = array(
http => array(
protocol_version => 1.1,
method => POST,
header => $header,
content => $content,
),
);
$context = stream_context_create($options);
for ($i = 0; $i < 1000; $i++) {
file_get_contents($url, false, $context);
}
?>

很多人写测试脚本的时候,喜欢在开始结束部分加上时间,这样相减就得到了代码实际运行的时间,其实这是不必要的,利用Linux自带的time就可以获取运行时间:

?
1
shell> time php /path/to/php/file
声明: 猿站网有关资源均来自网络搜集与网友提供,任何涉及商业盈利目的的均不得使用,否则产生的一切后果将由您自己承担! 本平台资源仅供个人学习交流、测试使用 所有内容请在下载后24小时内删除,制止非法恶意传播,不对任何下载或转载者造成的危害负任何法律责任!也请大家支持、购置正版! 。本站一律禁止以任何方式发布或转载任何违法的相关信息访客发现请向站长举报,会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。本网站的资源部分来源于网络,如有侵权烦请发送邮件至:2697268773@qq.com进行处理。
建站知识

小知识:linux下搭建hadoop环境步骤分享

2023-5-3 2:19:37

建站知识

小知识:如何在 Linux 下快速找到被删除的文件

2023-5-3 2:28:07

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索