定制nginx的gunzip模块
Table of Contents
1 gunzip and gzip
+---------------------------+ (3) +---------------------+ | |<------------------| | | Host 2: Nginx proxy | | Host 3: Upstream | | |------------------>| | +---------------------------+ (2) +---------------------+ | ^ (4) | | (1) v | +---------------------------+ | | | Host 2: Client | | | +---------------------------+
- gzip模块针对上图中的 (4) 。即返回给client的时候进行压缩。
- gunzip模块针对 (4) 。返回给client的时候,如果client是老式的不支持 解析压缩数据的客户1。把这个开关打开后,Host 2中的 nginx会把数据解压后再返回给client。如果client支持解压gzip文件 2,则Host 2在第 (4) 步的时候不会进行解压。
[X]
gzip开启后,第 (2) 步会不会进行压缩?这一步进不进行压缩要考虑两方面。Nginx请求给upstream时有没有加入对应的http头
"Accept-Encoding: gzip"
- Upstream支不支持压缩数据
[X]
gzip开启后, (3) 压缩了以后,在第 (4) 步会不会进行二次压缩?我 觉得应该不会了[X]
nginx的gunzip对第 (2) 步能不能生效?不会,nginx在host 2上,管 不了host 3上的server。
2 特殊情况的下定制nginx的gunzip模块
如果有一个第三方定制模块 my_module
,每次upstream返回给客户的数据
它都需要做一些加工处理。这种情况下,如果upstream返回的是压缩后的数据,
my_module
处理不了。
以 1 的图为例,现在 my_module
要求upstream (3) 回的消息不能
是zip过的。
现在使用nginx的gunzip模块,在我们 my_module
模块去处理upstream的
reponse之前对reponse先做处理,如果是zip的文件,就先unzip后再给
=my_module=模块处理。
支持这样的功能后,upstream可以通过压缩数据的方式减少upstream到proxy (内网)的网络流量3。
修改点:
- 编译nginx时,需要修改modules的加载顺序,使gunzip在
my_module
之 前加载4。 默认gunzip中有一个判断,如果客户发起的请求中显示有
Accept-encoding: gzip
这样的http header。表示客户支持解压zip文 件。这时默认gunzip模块不会对upstream传回来的压缩后的zip文件进行解 压的。这不符合我们的使用要求(我们要求是zip的数据就全部都解压让我 们的my_module
处理)。于是我们修改了一下原始的gunzip模块,如果 加载了我们的模块,则对response全部都做解压。然后再交给my_module
模块处理。static ngx_int_t ngx_http_gunzip_header_filter(ngx_http_request_t *r) { /* ... */ if (!r->gzip_tested) { /* 在这里做的判断 */ if (ngx_http_gzip_ok(r) == NGX_OK) { return ngx_http_next_header_filter(r); } } else if (r->gzip_ok) { return ngx_http_next_header_filter(r); } }
修改为:
if (!r->gzip_tested) { if (ngx_http_gzip_ok(r) == NGX_OK) { /** * Always unzip the gzip stream from upstream before * it send to RAS modules. */ if (r->headers_in.gunzip) { r->gzip_tested = 1; } else { return ngx_http_next_header_filter(r); } } } else if (r->gzip_ok) {
在结构体
ngx_http_headers_in_t
里面添加gunzip
位。如果配置文 件中设置了gunzip on
,则它的值应不为0。typedef struct { ngx_list_t headers; /* ... */ unsigned gunzip:2; } ngx_http_headers_in_t;