【问题标题】:HTTPS GZIP NGINX WTFHTTPS GZIP NGINX WTF
【发布时间】:2016-06-27 05:59:29
【问题描述】:

我几天来一直在尝试让 nginx 提供 gzip 内容,主要是因为谷歌的速度测试告诉我这样做,我们正在努力提高我们的 SEO。我一生都无法理解这里出了什么问题:

我们位于防火墙后面,并在负载均衡器下为两个 Web 头提供服务。无论我尝试了什么,我都无法让响应标头返回content-encoding:gzip。但是,当我使用 curl 发出请求时,我可以。此外,当我通过 https 访问该站点时,我确实使用 gzip 得到了响应,但是它与 nginx 无关,因为我在 nginx 中关闭了 gzip,我仍然得到相同的响应。还有什么可以将内容作为 gzip 提供?

更新

好吧,很抱歉,在发布了几次都没有回应之后,我有点沮丧。以下是一些信息:

我们正在使用带有 php-fpm 的 nginx 1.8.0。该站点是一个 Magento 框架。我正在尝试提供使用 gzip 压缩的主要 html 页面以及包含的 css/javascript 文件。这些文件目前在响应标头中显示未压缩,Google pagespeed 也表示它们未压缩。这是我看到的示例响应标头

Cache-Control:max-age=31536000
Connection:keep-alive
Content-Type:application/x-javascript; charset=utf-8
Date:Tue, 15 Mar 2016 15:15:13 GMT
ETag:"pub1448944926;gz"
Expires:Wed, 15 Mar 2017 15:15:13 GMT
Keep-Alive:timeout=8
Last-Modified:Tue, 01 Dec 2015 04:42:06 GMT
Server:nginx
Transfer-Encoding:chunked
Vary:Accept-Encoding

当我通过 curl 请求页面时,我得到了 gzip 内容。

curl -I -H 'Accept-encoding:gzip' mysite.com 

我们已从负载均衡器中删除暂存站点,但问题仍然存在;消除负载均衡器可能出现的任何问题(目前)。

当我通过 https 访问网站时,我得到 gzip 内容,这是响应标头

Cache-Control:max-age=31536000
Connection:keep-alive
Content-Encoding:gzip
Content-Length:67085
Content-Type:application/x-javascript; charset=utf-8
Date:Tue, 15 Mar 2016 15:51:31 GMT
ETag:"pub1448944926;gz"
Expires:Wed, 15 Mar 2017 15:51:31 GMT
Keep-Alive:timeout=8
Last-Modified:Tue, 01 Dec 2015 04:42:06 GMT
Server:nginx
Vary:Accept-Encoding

这里是 nginx 的相关配置文件

nginx.conf

user                    nginx;
worker_processes        4;
pid                     /var/run/nginx.pid;
error_log               /var/log/nginx/error.log;

events {
    worker_connections  1024;
    multi_accept        on;
    use                 epoll;
}

http {
    include             /etc/nginx/mime.types;
    charset             utf-8;
    default_type        application/octet-stream;

    #access_log         /var/log/nginx/access.log main;
    access_log          off;

    log_format main     '$remote_addr - $remote_user [$time_local]     "$request" '
    '$status $body_bytes_sent "$http_referer" '
    '"$http_user_agent" "$http_x_forwarded_for"';

    # compression
    gzip                on;
    gzip_http_version   1.0;
    gzip_vary           on;
    gzip_comp_level     5;
    gzip_proxied        any;
    gzip_min_length    100;
    #   gzip_min_length     10240;
    gzip_buffers        16 8k;
    gzip_types          text/plain text/css application/x-javascript     text/comma-separated-values text/xml application/xml application/xml+rss     application/atom+xml text/javascript;
    #gzip_disable       "MSIE [1-6].(?!.*SV1)";

    # general options
    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         off;
    autoindex           off;
    server_tokens       off;
    merge_slashes       on;
    client_header_buffer_size           1k;
    client_body_buffer_size             32k;
    client_max_body_size                64m;
    server_names_hash_bucket_size       128;
    large_client_header_buffers         2 1k;

    # timeouts
    send_timeout                        10;
    keepalive_timeout                   2 8;
    keepalive_requests                  200;
    client_body_timeout                 12;
    client_header_timeout               12;
    reset_timedout_connection           on;

    # pass through from load balancer
    real_ip_header X-Forwarded-For;
    set_real_ip_from 0.0.0.0/0;

    # detect https
    map $scheme $fastcgi_https {
        default "";
        https on;
    }

    # PHP-FPM
    upstream phpfpm {
        server unix:/run/php-fpm/php-fpm.sock weight=1 max_fails=5     fail_timeout=10;
    }

    # include active sites
    include /etc/nginx/sites-enabled/*;
    server {
        listen 80 spdy default_server;
        root /var/www/mysite.com;
        location ^~ /app/                       { return 403; }
        location ^~ /includes/                  { return 403; }
        location ^~ /media/downloadable/        { return 403; }
        location ^~ /pkginfo/                   { return 403; }
        location ^~ /report/config.xml          { return 403; }
        location ^~ /var/                       { return 403; }
        location ^~ /lib/                       { return 403; }
        location ^~ /dev/                       { return 403; }
        location ^~ /RELEASE_NOTES.txt          { return 403; }
        location ^~ /downloader/pearlib         { return 403; }
        location ^~ /downloader/template        { return 403; }
        location ^~ /downloader/Maged           { return 403; }
        location ~* ^/errors/.+\.xml            { return 403; }
    }

}

启用站点/我的站点

server {

    #mysiteip is an actual ip that I've removed for security

    listen mysiteip:80;  
    server_name www.test.mysite.com;
    return 301 $scheme://test.mysite.com$request_uri;
}
server {
    # settings
    listen mysiteip:80;
    listen mysiteip:443 ssl;
    server_name test.mysite.com;
    root /var/www/mysite.com/testing/current/;
    index index.html index.htm index.php;

    # security
    ssl_protocols TLSv1.2;
    ssl_ciphers RC4:HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    # SSL Certificate Settings
    ssl_certificate     /etc/nginx/ssl/bundle.crt;
    ssl_certificate_key /etc/nginx/ssl/star_mysite_com.key;


    access_log /var/log/nginx/mysite.access.log;
    error_log /var/log/nginx/www-mysite-com_error.log;

    # routes
    include /etc/nginx/conf.d/security.conf;
    include /etc/nginx/conf.d/assets.conf;
    include /etc/nginx/conf.d/rewrites.conf;

    # Attempt to serve the request by trying direct file, directory, Magento front controller

    large_client_header_buffers 8 16k;

    location / {
        try_files $uri $uri/ /index.php?$args;
        expires max;
    }

    # The downloader has its own index.php that needs to be used
    location ~* ^(/downloader)(.*) {
        try_files $uri $uri/ /downloader/index.php$1;
    }

    # REST API endpoint
    location /api {
        rewrite ^/api/rest /api.php?type=rest last;
        rewrite ^/api/v2_soap /api.php?type=v2_soap last;
        rewrite ^/api/soap /api.php?type=soap last;
    }

    # Pass PHP scripts to PHP-FPM daemon
    location ~* \.php$ {
        # filter out problem conditions
        location ~ \..*/.*\.php$ { return 404; }

        # bring in parameters
        include /etc/nginx/conf.d/fastcgi.conf;
        fastcgi_param MAGE_RUN_CODE default;
        fastcgi_param MAGE_RUN_TYPE store;

        # DEVELOPER MODE
        #fastcgi_param MAGE_IS_DEVELOPER_MODE true;

        # send requests to upstream, but blacklist media location from fcgi
        if ($uri !~ "^/(media)/") {
            fastcgi_pass phpfpm;
        }
    }
}

conf.d/rewrites.conf

# I am using this rewrite for the fooman speedster extension

location /skin/m {
   rewrite ^/skin/m/([^/]+)(/.*.(js|css))$ /lib/minify/m.php?f=$2&d=$1;
}

任何关于发生了什么或做错了什么的见解将不胜感激。如果需要,我可以提供更多信息。 Fooman 的重写也用于缩小,即使没有安装此扩展并且删除了重写,我仍然没有得到 gzip。

【问题讨论】:

  • 投了两次票,没有建设性的批评......不,这不仅仅是因为谷歌页面速度这么说,而是我们正在努力更新它。你想看看 nginx.conf 吗?没有什么问题。给出一个理由来否决这个问题。我只是想知道是否有人遇到过这样的情况以及他们可能采取了哪些措施来解决。
  • 我没有投反对票,但您并没有真正给任何人任何继续下去的机会。你是什​​么意思它适用于curl和https?那什么时候不行呢?您是否直接连接到网络服务器,所以是 LoadBalancer 有问题?此外,即使有一个项目没有经过 gzip 压缩,Google 的 Speed Test 也会对此进行标记,并且这可能是第三方内容(其中一些甚至由 Google 托管!)因此请扩展该点以查看哪些项目没有经过 gzip 压缩。
  • 哦,这不是关于编程,所以另一个拒绝投票的原因。他们建议姐妹网站 serverfault.com(仅适用于专业的“SA”,因此也经常拒绝此类问题)或unix.stackexchange.com(其章程说它更多地用于操作系统而不是在其上运行的软件)。恕我直言,网络服务器配置是成为网络开发人员的重要组成部分,但这里的很多人不同意将这些问题放在 SO 上是正确的。
  • 当您使用外部网站(例如 web-sniffer.net)时,您是否看到您的内容被压缩了?您是否知道 nginx 只会压缩您的静态内容(并且只压缩您定义的内容)并且动态 html 页面由 php 直接压缩(或您使用的任何内容)?如果是,请发布您的 nginx.conf 文件并说明哪些文件类型没有被 gzip(如果可能,请提供 url)
  • @BazzaDP 谢谢。我已经更新了我原来的问题。如果您仍然觉得这属于其他网站,请指出正确的方向,我会在其他地方查询。

标签: nginx https gzip


【解决方案1】:

您的 HTTP 响应可能已被缓存。这些 HTTP 标头泄露了它:

Cache-Control:max-age=31536000
Expires:Wed, 15 Mar 2017 15:15:13 GMT

这基本上告诉每个请求响应的人在他们认为合适的时候缓存响应,因为它在 2017 年 3 月之前都是有效且可缓存的。在您的示例中,这是针对 Javascript 的,所以很好,但是如果您再次测试资源,那么很有可能返回的是旧响应。您需要确保每个缓存都被清空并且没有代理缓存响应。否则,您可能会从中间位置而不是您的 Nginx 服务器获得响应,因此在这种情况下您无法验证任何 GZIP 设置。

HTTPS 请求通常不会被任何代理缓存(因为它们看不到内容),所以这可能是它在那里工作的原因。

您的配置中的以下几行可能会导致意外缓存:

location / {
    try_files $uri $uri/ /index.php?$args;
    expires max;
} 

Nginx 在这里使用 expires 指令为所有请求添加 expires 和 max-age 缓存控制头,甚至是动态请求。您应该使用此标头检查您的 HTML/PHP 页面是否未缓存,这是否可能是问题的一部分。

【讨论】:

    【解决方案2】:

    由于赏金,现在无法添加评论。 @iquiot @iquito 谢谢我禁用了最大过期并且没有运气。我追查到这是在 Fooman 扩展中设置的。并将 max-age 设置为零。这是新的响应头...但仍然没有 gzip

    Cache-Control   max-age=0
    Connection  keep-alive
    Content-Type    text/css; charset=utf-8
    Date     Thu, 17 Mar 2016 19:35:05 GMT
    Etag    "pub1457625059;gz"
    Last-Modified Thu, 10 Mar 2016 15:50:59 GMT
    Server nginx/1.8.0
    Transfer-Encoding chunked
    Vary    Accept-Encoding
    

    更新:

    我将自己从大局中删除,以尝试调试此问题。我创建了一个 test.html 文件并使用它来尝试查看是否可以进行任何类型的压缩。我注意到的一件奇怪的事情是,如果我将 gzip_min_length 设置为 100,当内容低于 100 时,我会在标题中获得内容长度,但是一旦超过 100,内容长度就会消失。

    更新 2: 使用 curl 时,设置的任何类型的“Accept:”标头都不会在响应中返回 gzip。这可能是罪魁祸首吗?

    更新 3: 将这个小工具用于 Firefox https://addons.mozilla.org/en-US/firefox/addon/modify-headers/developers 我能够修改发送的标题。 通过完全禁用用户代理标头,我现在可以使用内容编码 gzip 获得正确的响应标头。但是,我的 nginx 配置中没有任何为 gzip 设置的禁用参数,它会给出这种行为。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-24
      • 2018-02-03
      • 2017-02-08
      • 2012-01-20
      • 1970-01-01
      • 2014-03-14
      • 2020-08-04
      • 1970-01-01
      相关资源
      最近更新 更多