技术解析

Nginx 反代 Gzip 内容时, sub_filter 等 content filter 无效的另一种解决
0
2021-05-20 21:18:07
idczone
大家Nginx 反代时很常见的一个问题就是 sub_filter 无效。因为浏览器都是允许压缩的,所以请求头都是带 Accept-Encoding: gzip 的。而 Nginx 的 sub_filter 无法处理压缩过的请求, Nginx 自身也不会解压。事实上,要想写一个解压的插件也是不可能的,因为 Nginx 目前并没有 input filtering 相关的接口。

一般网上的解决办法都是 proxy_set_header Accept-Encoding "";禁用上游的压缩,对客户端的压缩不受影响。但是这样入站带宽就多很多了。一个可行的改进是活用 map ,只禁用常见的 html 内容的压缩。但是这样对纯网页效果依然有限。 CrystalACG 上即使缓存命中率过半(对纯网页几乎没有静态内容的 dmm 来说很高了),入站带宽依然超过出站。

最近尝试了另一种办法,效果不错。尽管 Nginx 没有 input filtering ,但我们可以反代自身,利用 gunzip 模块先解压。这样会有本地流量,但用 unix socks 的话额外开销只有 nginx 重新解析一次请求以及数据内存拷贝一次。几乎可以忽略。gzip 本身是很低开销的算法。就算将来Nginx加入了input filtering的支持,性能也不会比这个方案好很多。而且大多数反代站瓶颈都在带宽,CPU多一点无所谓。

新建一个 gunzip.conf :
https://gist.github.com/renyidong/大带宽服务器bf8ebdff6a2d48e05324
想不到還有這種方法,學習了

Nice one!

好机智

Nice !

其实是因为 gunzip 模块默认是尊重客户端请求,如果是 accept gzip 的就不解压;
我的方案是 patch 了 gunzip 模块,添加了一个 gunzip 的 force 指令,然后输出的时候再由 gzip 模块压回去
不过楼主这个思路还是挺不错的。

mark

马克,备用。

好机制。

是个好办法。。当年没想到,还用 lua 手工解压。。。











昨晚研究了一下搂住的配置,部分成功,还有些问题。
用的是这个配置:
http://jude.me/2014/10/04/twitter-mirror-2.html
今天按照 的思路改了一下 ngx 的代码,是不是这样写?
https://null.cmheia.com/nginx-1.9.6-gunzip_always-patch.diff.7z


不要用 if 判断 80 ,所有 80 直接 301 https ,根本不需要 if
你这一堆一堆的 subs_filter ,不能用 regex 么?既然有野卡,不能用泛域名么?
有问题贴一下具体的问题配置,你的博客与本主题无关
没事 @ 所有人很好玩么?

其实没什么技术含量,就是加了一个 if 在外面,我摘取修改部分的源码:
http://pastebin.com/hev12rvn

我也是这样改的代码。不过测试结果是 subs_filter 失效了。
后来我在这个 if 块前后增加了 debug
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "gunzip always: %d", conf->always);
输出的日志中也看到了相应的文字:
gunzip always: 1
gunzip always--
但是其中 subs_filter 还是失效,目前还未解决。
相关 diff 及 conf 见 10L 的 7z 链接。
------
to ryd994 :那个博客不是我的。
不,你该是误解了。

你检查一下模块调用的顺序,确认 gunzip 在 subs 前面

nginx lua 模块可以 input filter 。。我现在把客户端的加密数据在 nginx 解密丢给后端,然后把后端的数据加密后压缩给客户端

因为有人问了,有个大哥把你的链接写上去了,https://www.v2ex.com/t/397854#reply7

楼主,gunzip.conf 的配置已经无法访问了

受教了,这个思路很可以

gunzip.conf 的内容可以直接贴出来吗?

数据地带为您的网站提供全球顶级IDC资源