1. 异常现象

由于项目过于仓促上线,前期没有很好的进行性能优化导致使用js等静态资源些许有些缓慢,故而稳固后进行性能优化,但是出现了一个比较有趣的现象就是开启gzip后,响应的静态资源响应头中没有出现 content-encoding: gzip 本篇章来对其进行记录,以下为项目中使用的gzip配置片段。

#开启gzip压缩
gzip on;
#设置允许压缩的页面最小字节数,页面字节数从header头的Content-Length中获取,默认值是0,不管页面多大都进行压缩,建议设置成大于1K,如果小与1K可能会越压越大。
gzip_min_length 2k;
#压缩缓冲区大小,表示申请4个单位为32K的内存作为压缩结果流缓存,默认值是申请与原始数据大小相同的内存空间来存储gzip压缩结果。
gzip_buffers 4 32k;
#压缩比例,用来指定GZIP压缩比,1压缩比最小,处理速度最快,9压缩比最大,传输速度快,但是处理慢,也比较消耗CPU资源。
gzip_comp_level 5;
#用来指定压缩的类型
gzip_types text/plain application/javascript application/json application/x-javascript text/css application/xml text/javascript application/vnd.ms-excel application/x-httpd-php image/jpeg image/gif image/png;
#varyheader支持,该选项可以让前端的缓存服务器缓存经过GZIP压缩的页面。
gzip_vary off;
#由于IE6对gzip压缩支持的不是很好,所以这里配置agent是IE6以下的版本,则不进行gzip压缩
gzip_disable "MSIE [1-6]\.";

2. 排查流程

由于 A 项目嵌套了 B 项目,我通过 proxy_pass 反向代理来加载 B 项目的资源。 A 和 B 项目都使用相同的 nginx.conf 配置。

kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
  name: xxxx-web
  namespace: xxxx
  annotations:
    kubernetes.io/ingress.class: nginx
    kubesphere.io/alias-name: tanqidi
    kubesphere.io/creator: tanqidi
    kubesphere.io/description: tanqidi
    nginx.ingress.kubernetes.io/proxy-connect-timeout: '600'
    nginx.ingress.kubernetes.io/proxy-read-timeout: '600'
    nginx.ingress.kubernetes.io/proxy-send-timeout: '600'
    nginx.ingress.kubernetes.io/server-snippet: >
      proxy_set_header X-Forwarded-Proto $scheme;

      location ~ ^/ems-mobile-proxy(/.*\.(js|css|jpg|png|gif|ico|svg|html)|/?)$
      {
          rewrite ^/ems-mobile-proxy(/.*)$ $1 break;
          proxy_pass http://ems-mobile-web.fssc:80;
          proxy_set_header Host $host;
          proxy_set_header X-Real-IP $remote_addr;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header X-Forwarded-Proto $scheme;
      }
spec:
  tls:
    - hosts:
        - xxxx.uat.tanqidi.com
      secretName: tanqidi-uat-ssl
  rules:
    - host: xxxx.uat.tanqidi.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: form-web
                port:
                  number: 80
    

有趣的情况是,直接访问域名时会收到 Gzip 压缩响应,但在通过 proxy_pass 反向代理后,响应就没有 Gzip 压缩了。经过了解后发现问题的根源在于默认情况下,Nginx 与后端的 upstream 服务器之间使用的是 HTTP/1.0 协议。在 HTTP/1.0 协议中,Nginx 并不会启用 Gzip 压缩,因此当请求通过 proxy_pass 代理到目标服务器时,由于协议降级为 1.0,Gzip 压缩无法生效。

Gzip 采用http协议版本默认是1.1 ,对于1.0的请求不会压缩,如果设置成1.0表示http1.0以上的版本都会压缩。(如果使用了proxy_pass 进行反向代理,那么nginx和后端的 upstream server之间默认是用 http/1.0协议通信的。)

加上 gzip_http_version 1.0; 配置成功后从原来的每个300kb左右降到每个70kb

9017b617-723f-4fd7-a309-9394b2ecc894.jpeg

image-gmlc.png