V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
NGINX
NGINX Trac
3rd Party Modules
Security Advisories
CHANGES
OpenResty
ngx_lua
Tengine
在线学习资源
NGINX 开发从入门到精通
NGINX Modules
ngx_echo
ryd994
V2EX  ›  NGINX

Nginx 反代 Gzip 内容时, sub_filter 等 content filter 无效的另一种解决

  •  
  •   ryd994 ·
    ryd994 · 2015-11-09 23:28:27 +08:00 · 16525 次点击
    这是一个创建于 3334 天前的主题,其中的信息可能已经有所发展或是发生改变。
    大家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 :
    修改原来的代理配置:
    proxy_pass http://unix:/var/run/nginx-gunzip.sock:$request_uri;
    proxy_set_header Host $host;
    proxy_set_header Accept-Encoding "";

    这个办法可以结合map,只反代要替换的内容,进一步减少开销。现在 CrystalACG 入站流量只有原来的一半略多,出站的 2/3 不到。
    第 1 条附言  ·  2017-10-16 07:33:46 +08:00
    为啥好多人突然关注这个陈年老贴。。。。
    第 2 条附言  ·  2018-10-10 14:43:05 +08:00
    20 条回复    2021-07-29 20:02:18 +08:00
    auzeonfung
        1
    auzeonfung  
       2015-11-09 23:35:21 +08:00
    想不到還有這種方法,學習了
    Pastsong
        2
    Pastsong  
       2015-11-09 23:35:30 +08:00
    Nice one!
    maemual
        3
    maemual  
       2015-11-10 00:32:35 +08:00 via iPhone
    好机智
    feather12315
        4
    feather12315  
       2015-11-10 00:45:08 +08:00 via Android
    Nice !
    BOYPT
        5
    BOYPT  
       2015-11-10 00:49:38 +08:00
    其实是因为 gunzip 模块默认是尊重客户端请求,如果是 accept gzip 的就不解压;
    我的方案是 patch 了 gunzip 模块,添加了一个 gunzip 的 force 指令,然后输出的时候再由 gzip 模块压回去

    不过楼主这个思路还是挺不错的。
    br00k
        6
    br00k  
       2015-11-10 08:30:23 +08:00 via Android
    mark
    Orzpls
        7
    Orzpls  
       2015-11-10 09:46:01 +08:00 via Android
    马克,备用。
    lovedboy
        8
    lovedboy  
       2015-11-10 09:48:23 +08:00
    好机制。
    phithon
        9
    phithon  
       2015-11-10 10:31:01 +08:00
    是个好办法。。当年没想到,还用 lua 手工解压。。。
    cmheia
        10
    cmheia  
       2015-11-10 12:00:25 +08:00
    @ryd994

    @auzeonfung
    @Pastsong
    @maemual
    @feather12315
    @BOYPT
    @br00k
    @Orzpls
    @lovedboy
    @phithon

    昨晚研究了一下搂住的配置,部分成功,还有些问题。
    用的是这个配置:
    http://jude.me/2014/10/04/twitter-mirror-2.html

    今天按照 @BOYPT 的思路改了一下 ngx 的代码,是不是这样写?
    https://null.cmheia.com/nginx-1.9.6-gunzip_always-patch.diff.7z
    ryd994
        11
    ryd994  
    OP
       2015-11-10 15:08:44 +08:00
    @cmheia
    不要用 if 判断 80 ,所有 80 直接 301 https ,根本不需要 if
    你这一堆一堆的 subs_filter ,不能用 regex 么?既然有野卡,不能用泛域名么?
    有问题贴一下具体的问题配置,你的博客与本主题无关
    没事 @ 所有人很好玩么?
    BOYPT
        12
    BOYPT  
       2015-11-10 21:44:00 +08:00
    @cmheia 其实没什么技术含量,就是加了一个 if 在外面,我摘取修改部分的源码:
    http://pastebin.com/hev12rvn
    cmheia
        13
    cmheia  
       2015-11-10 23:08:07 +08:00
    @BOYPT 我也是这样改的代码。不过测试结果是 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 :那个博客不是我的。
    不,你该是误解了。
    ryd994
        14
    ryd994  
    OP
       2015-11-11 00:01:52 +08:00
    @cmheia 你检查一下模块调用的顺序,确认 gunzip 在 subs 前面
    fengjianxinghun
        15
    fengjianxinghun  
       2015-11-14 20:33:15 +08:00 via iPad
    nginx lua 模块可以 input filter 。。我现在把客户端的加密数据在 nginx 解密丢给后端,然后把后端的数据加密后压缩给客户端
    a1044634486
        16
    a1044634486  
       2017-10-16 10:09:30 +08:00
    因为有人问了,有个大哥把你的链接写上去了,https://www.v2ex.com/t/397854#reply7
    xiaoxiaocai1
        17
    xiaoxiaocai1  
       2018-10-10 11:13:08 +08:00
    楼主,gunzip.conf 的配置已经无法访问了
    EMLink
        18
    EMLink  
       2019-08-19 09:02:28 +08:00
    受教了,这个思路很可以
    iyangyuan
        19
    iyangyuan  
       2019-09-11 14:17:31 +08:00
    gunzip.conf 的内容可以直接贴出来吗?
    hb751968840
        20
    hb751968840  
       2021-07-29 20:02:18 +08:00
    有用
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1309 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 17:48 · PVG 01:48 · LAX 09:48 · JFK 12:48
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.