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

请教 Nginx 中对 application/json 格式进行 gzip 压缩无效的问题?

  •  
  •   cruelcage · 2015-01-27 13:40:42 +08:00 · 14864 次点击
    这是一个创建于 3594 天前的主题,其中的信息可能已经有所发展或是发生改变。
    nginx.conf

    gzip on;
    gzip_min_length 1k;
    gzip_buffers 4 16k;
    gzip http_version 1.0;
    gzip_comp_level 2;
    gzip_types text/plain application/json;
    gzip_vary on;
    gzip_proxied expired no-cache no-store private auth;


    我用的是web.py框架
    web.header("Content-Type", "application/json")
    web.header("Content-Encoding", "gzip")


    curl -I返回的是

    HTTP/1.1 200 OK
    Server: nginx
    Date: Tue, 27 Jan 2015 05:32:34 GMT
    Content-Type: application/json
    Connection: keep-alive
    Content-Encoding: gzip
    Set-Cookie: webpy_session_id=0b019c20c14f05cd3db73afe18ca07902928889d; Path=/; httponly

    wget --header="accept-encoding:gzip"之后得到的格式不是压缩格式

    请问是哪里出了问题,找半天还是没找到。
    26 条回复    2015-01-29 12:04:06 +08:00
    ryd994
        1
    ryd994  
       2015-01-27 16:07:22 +08:00 via Android
    Content-Encoding: gzip
    这不就是压缩过了么!curl自动帮你解了而已
    cruelcage
        2
    cruelcage  
    OP
       2015-01-27 16:17:07 +08:00
    @ryd994 我用wget带Accept-Encoding头下下来的是文本格式,不是压缩包,照理说不应该是压缩包吗?我试过其他网站的下下来是压缩包。
    ryd994
        3
    ryd994  
       2015-01-27 16:25:14 +08:00 via Android
    其他网站上的content-type是什么?后缀是什么?
    BOYPT
        4
    BOYPT  
       2015-01-27 16:27:06 +08:00
    你程序里面不要输出Content-Encoding: gzip
    由nginx来处理。

    curl -v --compressed http:/xxxxxx > /dev/null

    这样只要你看到有Content-Encoding: gzip,说明就是压缩的。
    cruelcage
        5
    cruelcage  
    OP
       2015-01-27 16:42:31 +08:00
    @ryd994 比如https://api.github.com/events返回的是Content-Type: application/json; charset=utf-8
    cruelcage
        6
    cruelcage  
    OP
       2015-01-27 16:44:02 +08:00
    @BOYPT 我删掉web.header("Content-Encoding", "gzip")后是输出Content-Encoding: gzip没错,但是wget下来的依然是文本格式而且大小也没有压缩过,size有大于1k。
    cruelcage
        7
    cruelcage  
    OP
       2015-01-27 16:45:37 +08:00
    ryd994
        8
    ryd994  
       2015-01-27 17:05:12 +08:00 via Android
    不能啊,按照HTTP协议规范,设置了content-encoding就肯定得有相应的处理啊。
    ryd994
        9
    ryd994  
       2015-01-27 17:12:46 +08:00 via Android
    你用html文件试试看,如果html没问题的话,那就是gzip_types的问题 http://nginx.org/en/docs/http/ngx_http_gzip_module.html#gzip_types

    你给个测试链接我看看,记得限制请求频率免得被人DOS了
    ryd994
        10
    ryd994  
       2015-01-27 17:14:12 +08:00 via Android
    等等,你是app里设定的gzip的header?
    不需要啊,nginx如果压缩了会自己设置的,不要在app里设
    clino
        11
    clino  
       2015-01-27 17:23:57 +08:00
    建议用wireshark抓包诊断比较快
    cruelcage
        12
    cruelcage  
    OP
       2015-01-27 17:27:53 +08:00
    @ryd994 我在本地测试的。。
    BOYPT
        13
    BOYPT  
       2015-01-27 17:41:46 +08:00
    @cruelcage 因为wget自动解压了呀,你纠结这个干嘛。
    cruelcage
        14
    cruelcage  
    OP
       2015-01-27 18:00:08 +08:00 via Android
    @BOYPT 不科学啊,没有压缩效果阿,照理说我加了accept-encodingwget不会解压阿
    ryd994
        15
    ryd994  
       2015-01-27 18:16:22 +08:00
    @BOYPT wget如果是手动设置header,不会解压,你可以用上面那个github的url试试

    @cruelcage 不要在python里设定content-encoding,让nginx自己来。如果有content-encoding,nginx就认为已经编码过了
    cruelcage
        16
    cruelcage  
    OP
       2015-01-27 18:51:26 +08:00 via Android
    @ryd994 我去掉了,效果一样。。
    ryd994
        17
    ryd994  
       2015-01-27 19:21:10 +08:00 via Android
    你用个本地文件先试试
    cruelcage
        18
    cruelcage  
    OP
       2015-01-27 20:35:37 +08:00
    @ryd994 我用curl -H "Accept-Encoding:gzip"得到的是gzip格式的了,然后再gunzip后正常,看来是wget自动解压缩了,坑爹,我要仔细研究下wget。感谢相助。
    cruelcage
        19
    cruelcage  
    OP
       2015-01-27 20:36:33 +08:00
    @ryd994 诶,不过为什么github的那个用wget就能正常得到gzip格式的呢,看来还是配置有问题。。
    zhicheng
        20
    zhicheng  
       2015-01-27 21:00:17 +08:00
    @ryd994 你需要再仔细的读一遍 RFC 了。

    gzip 并不是强制的,如果 client 不设置可以接收 gzip ,那么正常的 server 是不会发送 gzip 编码过的 body ,这是内容协商的一部分。
    ryd994
        21
    ryd994  
       2015-01-28 00:19:02 +08:00 via Android
    @zhicheng 问题是现在服务器有content-encoding这个header,却没有压缩
    ryd994
        22
    ryd994  
       2015-01-28 00:34:44 +08:00 via Android
    @zhicheng 事实证明楼主自己二了,不知道wget会自动解码
    zhicheng
        23
    zhicheng  
       2015-01-28 00:46:53 +08:00
    @ryd994 要不怎么叫内容协商呢?
    服务器端有,但是客户端没有发送支持 gzip 的 Accept-encoding ,服务器是不会压缩的。当然可以让服务器强制 gzip 压缩,只是默认服务器不会这样,违反 RFC 。
    另外那个 Content-Encoding 的头,是自己设置的。不是 Nginx 设置的。。。。
    cruelcage
        24
    cruelcage  
    OP
       2015-01-28 09:10:21 +08:00
    @zhicheng @ryd994 最终结果是这样

    有自己设置的web.header("Content-Encoding", "gzip")后curl -I输出

    HTTP/1.1 200 OK
    Server: nginx
    Date: Wed, 28 Jan 2015 01:13:13 GMT
    Content-Type: application/json
    Connection: keep-alive
    Content-Encoding: gzip

    wget --header="accept-encoidng:gzip"返回文本格式

    ------------------------------------------------------------------------------------------------------------------------

    去掉自己设置的web.header("Content-Encoding", "gzip")后curl -I输出:

    HTTP/1.1 200 OK
    Server: nginx
    Date: Wed, 28 Jan 2015 01:08:13 GMT
    Content-Type: application/json
    Connection: keep-alive
    Vary: Accept-Encoding

    wget --header="accept-encoidng:gzip"返回gzip格式
    sampeng
        25
    sampeng  
       2015-01-28 13:58:19 +08:00
    gzip_min_length 1k;

    1k=1024个字节。你得json多大到1k啊。。

    补充一下,1k你就压缩,效率和压缩比反而低。

    json不需要gzip。除非上百k的。其他反而增加负担
    wuljy
        26
    wuljy  
       2015-01-29 12:04:06 +08:00
    1. 自己不要随意加头
    2. 小文件不要随意zip
    3. 大文件不要用json
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1219 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 23:54 · PVG 07:54 · LAX 15:54 · JFK 18:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.