Nginx Gzip压缩配置指南

描述

一、概述

1.1 背景介绍

说起Gzip压缩,可能很多人觉得这是个老生常谈的话题。但我在这几年的运维工作中发现,真正把Gzip配置到位的网站其实不多。去年帮一个客户做性能优化,他们的网站日均带宽消耗在2TB左右,一看Nginx配置,Gzip居然只开了默认的gzip on,压缩级别是1,很多该压的文件类型都没加上。调整完配置后,带宽直接降到800GB,每个月省下来的CDN费用够给团队发几次下午茶了。

Gzip是HTTP/1.1引入的内容编码机制,通过DEFLATE算法对响应体进行压缩。文本类内容(HTML、CSS、JS、JSON、XML)压缩率通常能达到60%-80%,这意味着原本100KB的文件传输时只需要20-40KB。在移动网络环境下,这个优化效果特别明显。

现代浏览器都支持Gzip解压,服务端压缩+客户端解压这个过程对用户来说完全透明,但带来的体验提升却是实实在在的。

1.2 技术特点

压缩原理

Gzip基于LZ77算法和哈夫曼编码,通过查找重复字符串并用更短的引用替代,再对结果进行熵编码。对于包含大量重复模式的文本文件效果最好,对已经压缩过的文件(图片、视频、压缩包)几乎没有效果。

压缩级别

Nginx支持1-9九个压缩级别:

级别1:压缩速度最快,压缩率最低

级别9:压缩率最高,但CPU消耗也最大

级别5-6:通常是性能和压缩率的最佳平衡点

实测数据显示,从级别5到级别9,压缩率只提升3-5%,但CPU消耗增加40%以上。所以生产环境一般不建议用9。

静态预压缩

Nginx的gzip_static模块支持预压缩文件。如果存在file.js.gz,直接返回压缩文件而不用实时压缩,彻底消除CPU开销。这是高并发场景下的杀手级优化。

1.3 适用场景

适合Gzip压缩的内容

HTML/CSS/JavaScript

JSON/XML/SVG

纯文本文件(txt、csv、log)

字体文件(woff虽然已压缩,但gzip还能再压10%左右)

不适合Gzip压缩的内容

图片(JPEG、PNG、WebP本身已压缩)

视频/音频文件

压缩包(zip、gz、rar)

PDF文件(内部已压缩)

典型应用场景

API服务器:JSON响应压缩效果极佳

静态资源服务器:CSS/JS压缩节省大量带宽

文档站点:HTML内容压缩率高

日志分析平台:大量文本数据传输

1.4 环境要求

组件 版本要求 说明
操作系统 Rocky Linux 9 / Ubuntu 24.04 LTS 内核4.x以上
Nginx 1.26.x / 1.27.x 需包含ngx_http_gzip_module
可选模块 gzip_static 静态预压缩支持
可选模块 gunzip 为不支持gzip的客户端解压
CPU 多核推荐 实时压缩消耗CPU
内存 每连接约256KB gzip缓冲区大小

二、详细步骤

2.1 准备工作

确认Nginx已编译gzip模块

 

# 查看编译参数
nginx -V 2>&1 | tr ' ' '
' | grep gzip

# 输出应包含:
# --with-http_gzip_static_module
# --with-http_gunzip_module

# 如果缺少gzip_static模块,需要重新编译或安装带模块的版本
# 官方仓库的nginx默认包含这些模块

 

准备测试文件

 

# 创建测试目录
mkdir -p /data/gzip-test

# 生成测试文件
cat > /data/gzip-test/test.html << 'EOF'



    
    Gzip压缩测试
    


    
       
           

Gzip压缩效果测试页面

       
       
           

这是一个用于测试Nginx Gzip压缩效果的页面。

           

重复内容有助于提高压缩率。

           

重复内容有助于提高压缩率。

           

重复内容有助于提高压缩率。

       
   
EOF # 创建一个大的JS文件用于测试 curl -o /data/gzip-test/jquery.js https://code.jquery.com/jquery-3.7.1.js 2>/dev/null     || echo'console.log("test");' > /data/gzip-test/jquery.js # 创建JSON测试文件 cat > /data/gzip-test/data.json << 'EOF' {     "users": [         {"id": 1, "name": "张三", "email": "zhangsan@example.com"},         {"id": 2, "name": "李四", "email": "lisi@example.com"},         {"id": 3, "name": "王五", "email": "wangwu@example.com"}     ],     "total": 3,     "page": 1,     "pageSize": 10 } EOF # 查看文件大小 ls -lh /data/gzip-test/

 

安装测试工具

 

# Rocky Linux
dnf install curl httpd-tools -y

# Ubuntu
apt install curl apache2-utils -y

 

2.2 核心配置

基础Gzip配置

 

# /etc/nginx/nginx.conf 或 /etc/nginx/conf.d/gzip.conf

http {
    # ==================== Gzip基础配置 ====================

    # 开启gzip压缩
    gzip on;

    # 压缩级别:1-9,推荐5-6
    # 级别越高压缩率越好但CPU消耗越大
    gzip_comp_level 5;

    # 最小压缩文件大小
    # 小于这个值的文件不压缩(压缩收益小)
    gzip_min_length 1024;

    # 压缩缓冲区
    # 32个4k的缓冲区,用于存储压缩结果
    gzip_buffers 32 4k;

    # 压缩HTTP版本
    # 对HTTP/1.0也启用压缩(兼容老代理)
    gzip_http_version 1.0;

    # ==================== 压缩类型配置 ====================

    # 需要压缩的MIME类型
    # 注意:text/html默认已启用,不需要重复添加
    gzip_types
        # 文本类型
        text/plain
        text/css
        text/xml
        text/javascript
        # 应用类型
        application/json
        application/javascript
        application/x-javascript
        application/xml
        application/xml+rss
        application/xhtml+xml
        application/atom+xml
        application/rss+xml
        # 字体类型
        application/font-woff
        application/font-woff2
        application/vnd.ms-fontobject
        application/x-font-ttf
        font/opentype
        font/woff
        font/woff2
        # 图片类型(仅SVG,其他图片已压缩)
        image/svg+xml
        image/x-icon;

    # ==================== 代理相关配置 ====================

    # 针对代理请求的压缩策略
    # any: 对所有代理请求都压缩
    gzip_proxied any;

    # 其他可选值:
    # off: 禁止对代理请求压缩
    # expired: 响应头包含Expires且已过期
    # no-cache: 响应头包含Cache-Control: no-cache
    # no-store: 响应头包含Cache-Control: no-store
    # private: 响应头包含Cache-Control: private
    # no_last_modified: 响应头不包含Last-Modified
    # no_etag: 响应头不包含ETag
    # auth: 请求头包含Authorization
    # any: 所有代理请求

    # ==================== Vary头配置 ====================

    # 在响应头中添加Vary: Accept-Encoding
    # 告诉代理服务器根据Accept-Encoding缓存不同版本
    gzip_vary on;

    # ==================== 排除特定客户端 ====================

    # 禁止对特定User-Agent压缩
    # 某些老旧浏览器对gzip支持有问题
    gzip_disable "MSIE [1-6].";

    # 也可以用正则排除更多
    # gzip_disable "MSIE [1-6].|Mozilla/4";
}

 

静态预压缩配置(gzip_static)

这是我强烈推荐的优化方式,特别是对于前端构建产物:

 

http {
    # 开启静态预压缩
    # on: 查找.gz文件,找到就直接返回
    # off: 禁用
    # always: 始终返回.gz文件,不检查客户端是否支持
    gzip_static on;

    server {
        listen 80;
        server_name example.com;
        root /data/www;

        # 前端资源目录
        location /assets/ {
            # 启用静态预压缩
            gzip_static on;

            # 缓存控制
            expires 1y;
            add_header Cache-Control "public, immutable";
        }

        # API接口(实时压缩)
        location /api/ {
            # API响应需要实时压缩
            gzip on;
            gzip_comp_level 5;
            gzip_types application/json;

            proxy_pass http://backend;
        }
    }
}

 

预压缩文件生成脚本

 

#!/bin/bash
# generate_gzip.sh - 生成预压缩文件

STATIC_DIR=${1:-/data/www/assets}
GZIP_LEVEL=${2:-9}

echo"开始生成预压缩文件..."
echo"目录: $STATIC_DIR"
echo"压缩级别: $GZIP_LEVEL"

# 需要预压缩的文件类型
FILE_TYPES="css js html json xml svg txt"

for ext in$FILE_TYPES; do
    find "$STATIC_DIR" -name "*.$ext" -type f | whileread file; do
        # 跳过已经是.gz的文件
        [[ "$file" == *.gz ]] && continue

        gz_file="${file}.gz"

        # 如果.gz文件不存在或源文件更新,重新压缩
        if [[ ! -f "$gz_file" ]] || [[ "$file" -nt "$gz_file" ]]; then
            echo"压缩: $file"
            gzip -${GZIP_LEVEL} -c "$file" > "$gz_file"

            # 保持时间戳一致
            touch -r "$file""$gz_file"
        fi
    done
done

echo"预压缩完成!"

# 统计压缩效果
echo""
echo"=== 压缩效果统计 ==="
find "$STATIC_DIR" -name "*.gz" -type f | whileread gz_file; do
    orig_file="${gz_file%.gz}"
    if [[ -f "$orig_file" ]]; then
        orig_size=$(stat -c%s "$orig_file" 2>/dev/null || stat -f%z "$orig_file")
        gz_size=$(stat -c%s "$gz_file" 2>/dev/null || stat -f%z "$gz_file")
        ratio=$(echo"scale=2; (1 - $gz_size / $orig_size) * 100" | bc)
        echo"$orig_file: $orig_size -> $gz_size (节省 ${ratio}%)"
    fi
done

 

2.3 启动和验证

配置检查

 

# 检查配置语法
nginx -t

# 查看gzip相关配置
nginx -T | grep -i gzip

# 重载配置
nginx -s reload

 

基础验证

 

# 测试gzip是否生效
# 注意:必须发送Accept-Encoding头

# 不带压缩请求
curl -I http://localhost/test.html
# Content-Length: 1234 (原始大小)

# 带压缩请求
curl -I -H "Accept-Encoding: gzip" http://localhost/test.html
# Content-Encoding: gzip
# Content-Length: 456 (压缩后大小)
# Vary: Accept-Encoding

# 获取完整响应并解压
curl -H "Accept-Encoding: gzip" http://localhost/test.html | gunzip

 

详细测试脚本

 

#!/bin/bash
# test_gzip.sh - 测试Gzip压缩效果

URL=${1//localhost}
FILES=("test.html""jquery.js""data.json""style.css")

echo"=== Gzip压缩效果测试 ==="
echo"目标: $URL"
echo""

printf"%-30s %10s %10s %10s
""文件""原始大小""压缩大小""压缩率"
printf"%-30s %10s %10s %10s
""----""--------""--------""------"

for file in"${FILES[@]}"; do
    # 获取未压缩大小
    orig_size=$(curl -sI "$URL/$file" 2>/dev/null | grep -i content-length | awk '{print $2}' | tr -d '
')

    # 获取压缩后大小
    gzip_size=$(curl -sI -H "Accept-Encoding: gzip""$URL/$file" 2>/dev/null | grep -i content-length | awk '{print $2}' | tr -d '
')

    # 检查是否启用了压缩
    encoding=$(curl -sI -H "Accept-Encoding: gzip""$URL/$file" 2>/dev/null | grep -i content-encoding)

    if [[ -n "$encoding" ]] && [[ -n "$orig_size" ]] && [[ -n "$gzip_size" ]]; then
        ratio=$(echo"scale=1; (1 - $gzip_size / $orig_size) * 100" | bc)
        printf"%-30s %10s %10s %9s%%
""$file""$orig_size""$gzip_size""$ratio"
    else
        printf"%-30s %10s %10s %10s
""$file""$orig_size""${gzip_size:-N/A}""未压缩"
    fi
done

 

压力测试对比

 

# 无压缩测试
ab -n 10000 -c 100 http://localhost/jquery.js
# 记录:Requests per second, Transfer rate

# 有压缩测试
ab -n 10000 -c 100 -H "Accept-Encoding: gzip" http://localhost/jquery.js
# 记录:Requests per second, Transfer rate

# 对比传输量和吞吐量的变化

 

三、示例代码和配置

3.1 完整配置示例

生产环境完整配置

 

# /etc/nginx/conf.d/gzip-production.conf
# 生产环境Gzip完整配置

http {
    # ==================== Gzip全局配置 ====================

    # 基础开关
    gzip on;

    # 压缩级别:生产环境推荐5
    gzip_comp_level 5;

    # 最小压缩大小:小于1KB的文件不压缩
    gzip_min_length 1024;

    # 压缩缓冲区配置
    # 16个8k的缓冲区,适合中等大小文件
    gzip_buffers 16 8k;

    # HTTP版本
    gzip_http_version 1.1;

    # 启用Vary头
    gzip_vary on;

    # 对代理请求的处理
    gzip_proxied any;

    # 禁用对老旧IE的压缩
    gzip_disable "MSIE [1-6].(?!.*SV1)";

    # 压缩类型(完整列表)
    gzip_types
        # 文本
        text/plain
        text/css
        text/xml
        text/javascript
        text/x-component
        text/cache-manifest
        # 应用
        application/json
        application/javascript
        application/x-javascript
        application/xml
        application/xml+rss
        application/xhtml+xml
        application/atom+xml
        application/rss+xml
        application/ld+json
        application/manifest+json
        application/schema+json
        application/geo+json
        application/vnd.api+json
        application/vnd.ms-fontobject
        application/x-font-ttf
        application/x-font-opentype
        application/x-font-truetype
        application/x-web-app-manifest+json
        # 字体
        font/eot
        font/opentype
        font/otf
        font/woff
        font/woff2
        # 图片(仅矢量)
        image/svg+xml
        image/x-icon
        image/bmp
        image/vnd.microsoft.icon;

    # ==================== 静态预压缩 ====================

    # 全局开启静态预压缩
    gzip_static on;
}

 

分场景配置示例

 

server {
    listen 80;
    server_name example.com;
    root /data/www;

    # ==================== 场景一:静态资源CDN源站 ====================

    location /static/ {
        # 使用预压缩文件(最高压缩级别)
        gzip_static on;

        # 如果没有预压缩文件,实时压缩
        gzip on;
        gzip_comp_level 6;

        # 长缓存
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # ==================== 场景二:API响应压缩 ====================

    location /api/ {
        # API响应通常是JSON,必须实时压缩
        gzip on;
        gzip_comp_level 5;
        gzip_min_length 256;  # API响应可能较小,降低阈值
        gzip_types application/json;

        # 禁用代理缓存(API响应经常变化)
        add_header Cache-Control "no-store";

        proxy_pass http://api_backend;
        proxy_set_header Accept-Encoding "";  # 不让后端压缩,Nginx统一处理
    }

    # ==================== 场景三:HTML页面 ====================

    location / {
        gzip on;
        gzip_comp_level 5;
        gzip_types text/html;

        # HTML不缓存,保证获取最新内容
        expires -1;
        add_header Cache-Control "no-cache, must-revalidate";

        try_files $uri $uri/ /index.html;
    }

    # ==================== 场景四:大文件下载 ====================

    location /downloads/ {
        # 大文件不压缩,避免占用大量内存和CPU
        gzip off;

        # 开启sendfile高效传输
        sendfile on;
        tcp_nopush on;

        # 限速防止带宽耗尽
        limit_rate 1m;
    }

    # ==================== 场景五:WebSocket ====================

    location /ws/ {
        # WebSocket不能使用gzip
        gzip off;

        proxy_pass http://websocket_backend;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

 

3.2 实际应用案例

案例一:电商网站首页优化

我们有个电商客户,首页HTML有800KB(包含大量商品数据),加载时间超过3秒。

优化前的情况:

 

首页大小: 812KB
加载时间: 3.2s(3G网络)
Gzip: 未启用

 

优化方案:

 

location / {
    gzip on;
    gzip_comp_level 6;  # 首页访问频繁,适当提高压缩级别
    gzip_types text/html application/json;
    gzip_min_length 256;

    # 启用ETag便于缓存验证
    etag on;

    try_files $uri @backend;
}

location @backend {
    proxy_pass http://backend;

    # 后端响应也要压缩
    gzip on;
    gzip_proxied any;
}

 

优化后:

 

首页大小: 812KB -> 156KB(压缩率81%)
加载时间: 3.2s -> 0.8s
带宽节省: 约80%

 

案例二:API服务压缩优化

某金融APP后端API,每天数千万次调用,返回JSON数据。

问题分析:

 

平均响应大小: 15KB
日请求量: 5000万次
日带宽消耗: 约700TB
带宽成本: 高

 

配置方案:

 

upstream api_servers {
    server 10.0.1.10:8080;
    server 10.0.1.11:8080;
    keepalive 100;
}

server {
    listen 80;
    server_name api.example.com;

    location / {
        # JSON响应压缩
        gzip on;
        gzip_comp_level 5;
        gzip_min_length 512;
        gzip_types application/json;
        gzip_proxied any;
        gzip_vary on;

        proxy_pass http://api_servers;
        proxy_http_version 1.1;
        proxy_set_header Connection "";

        # 重要:告诉后端不要压缩,统一由Nginx处理
        proxy_set_header Accept-Encoding "identity";

        # 缓冲设置,避免边收边发
        proxy_buffering on;
        proxy_buffer_size 4k;
        proxy_buffers 8 32k;
    }
}

 

优化效果:

 

平均响应大小: 15KB -> 3KB(压缩率80%)
日带宽消耗: 700TB -> 140TB
月度带宽成本节省: 约560TB * 单价
CPU增加: 约15%(可接受)

 

案例三:前端构建产物预压缩

现代前端项目使用Webpack/Vite构建,结合CI/CD自动生成预压缩文件。

Vite配置:

 

// vite.config.js
import { defineConfig } from'vite'
import viteCompression from'vite-plugin-compression'

exportdefault defineConfig({
plugins: [
    viteCompression({
      algorithm: 'gzip',
      ext: '.gz',
      threshold: 1024,  // 大于1KB才压缩
      deleteOriginFile: false// 保留原文件
    }),
    // 同时生成Brotli压缩
    viteCompression({
      algorithm: 'brotliCompress',
      ext: '.br',
      threshold: 1024
    })
  ]
})

 

Nginx配置:

 

location /assets/ {
    # 优先返回Brotli压缩(压缩率更高)
    brotli_static on;

    # 其次返回Gzip
    gzip_static on;

    # 如果都没有,实时压缩
    gzip on;
    gzip_comp_level 5;

    expires max;
    add_header Cache-Control "public, immutable";
}

 

CI/CD pipeline脚本:

 

#!/bin/bash
# build.sh - 前端构建脚本

# 构建
npm run build

# 生成预压缩文件
cd dist

# Gzip压缩
find . -type f ( -name "*.js" -o -name "*.css" -o -name "*.html" -o -name "*.json" ) 
    -exec gzip -9 -k {} ;

# Brotli压缩(如果安装了brotli)
ifcommand -v brotli &> /dev/null; then
    find . -type f ( -name "*.js" -o -name "*.css" -o -name "*.html" -o -name "*.json" ) 
        -exec brotli -9 -k {} ;
fi

# 统计
echo"=== 压缩统计 ==="
du -sh dist/
find dist -name "*.gz" | wc -l
find dist -name "*.br" | wc -l

 

案例四:不同压缩级别性能对比测试

我在一台4核8G的服务器上做了详细测试,文件是280KB的jquery.min.js:

压缩级别 压缩后大小 压缩率 压缩耗时 QPS
1 98KB 65% 0.8ms 12000
2 94KB 66% 0.9ms 11500
3 91KB 67% 1.1ms 10800
4 88KB 69% 1.4ms 9500
5 85KB 70% 1.8ms 8200
6 84KB 70% 2.5ms 6800
7 83KB 70% 3.8ms 5200
8 82KB 71% 6.2ms 3500
9 82KB 71% 12ms 1800
预压缩 82KB 71% 0ms 35000

结论:

级别5是性价比最高的选择

级别6-9收益递减明显,不推荐

预压缩性能碾压实时压缩,强烈推荐

四、最佳实践和注意事项

4.1 最佳实践

1. 根据内容类型选择压缩策略

 

# 高频访问的静态资源:预压缩
location ~* .(js|css)$ {
    gzip_static on;
    gzip on;
    gzip_comp_level 5;
}

# 动态生成的内容:实时压缩
location /api/ {
    gzip on;
    gzip_comp_level 5;
}

# 已压缩的媒体文件:不压缩
location ~* .(jpg|jpeg|png|gif|mp4|webm|zip|gz)$ {
    gzip off;
}

 

2. 合理设置gzip_min_length

 

# 太小的文件压缩后可能反而变大(gzip头部开销)
# 推荐设置:
gzip_min_length 1024;  # 通用场景

# API场景可以降低阈值(JSON通常较小但压缩率高)
gzip_min_length 256;

 

3. gzip_vary必须开启

 

# 必须开启,否则CDN/代理可能返回错误的缓存
gzip_vary on;

# 这会在响应头添加:
# Vary: Accept-Encoding
# 告诉缓存服务器:同一URL根据Accept-Encoding返回不同内容

 

4. 统一在Nginx层压缩

 

# 不要让后端应用也压缩,会造成:
# 1. 重复压缩浪费CPU
# 2. 压缩策略不统一
# 3. 调试困难

location /api/ {
    proxy_pass http://backend;

    # 告诉后端不要压缩
    proxy_set_header Accept-Encoding "identity";

    # 由Nginx统一压缩
    gzip on;
    gzip_proxied any;
}

 

5. 监控压缩效果

 

# 自定义日志格式记录压缩信息
log_format compression '$remote_addr - $remote_user [$time_local] '
                       '"$request" $status $body_bytes_sent '
                       '"$http_referer" "$http_user_agent" '
                       '$gzip_ratio';

# $gzip_ratio 显示压缩比例,如 "2.50"表示压缩到原来的1/2.5

 

4.2 注意事项

常见错误表

错误 原因 解决方案
gzip不生效 请求头缺少Accept-Encoding 检查客户端/代理是否移除了该头
压缩率低 文件已压缩或内容随机性高 检查文件类型,已压缩文件不要重复压缩
CPU飙高 压缩级别过高或并发过大 降低压缩级别或使用预压缩
响应变慢 gzip_buffers配置不当 增大缓冲区或降低压缩级别
CDN缓存异常 未设置Vary头 开启gzip_vary on
部分请求未压缩 小于gzip_min_length 降低阈值或接受不压缩
乱码 客户端不支持gzip 使用gzip_disable排除

性能陷阱

 

# 陷阱1:对所有内容都压缩
# 错误
gzip_types *;
# 正确:只压缩文本类型

# 陷阱2:压缩级别设置过高
# 错误
gzip_comp_level 9;  # CPU杀手
# 正确
gzip_comp_level 5;  # 性价比最高

# 陷阱3:不限制最小压缩大小
# 错误
gzip_min_length 0;  # 所有文件都压缩
# 正确
gzip_min_length 1024;  # 小文件不压缩

# 陷阱4:对图片视频压缩
# 错误
gzip_types image/jpeg image/png video/mp4;
# 这些格式已经压缩过,再压缩只浪费CPU

# 陷阱5:没有预压缩高频文件
# 错误:每次请求都实时压缩
# 正确:构建时预压缩 + gzip_static on

 

安全考虑

 

# BREACH攻击防护
# 对包含敏感信息的HTTPS响应,攻击者可能通过压缩率变化推测内容
# 防护方案:
# 1. 对包含敏感数据的响应禁用压缩
location /api/sensitive/ {
    gzip off;
}

# 2. 在响应中添加随机填充
# 需要后端配合实现

# 3. 使用SameSite Cookie
add_header Set-Cookie "session=xxx; SameSite=Strict";

 

五、故障排查和监控

5.1 故障排查

问题一:Gzip完全不生效

 

# 排查步骤

# 1. 检查模块是否加载
nginx -V 2>&1 | grep -o 'http_gzip_module'

# 2. 检查配置是否生效
nginx -T | grep gzip

# 3. 测试请求
curl -I -H "Accept-Encoding: gzip" http://localhost/test.html

# 4. 如果响应头没有Content-Encoding: gzip,检查:
# - gzip是否为on
# - 文件类型是否在gzip_types中
# - 文件大小是否大于gzip_min_length
# - 是否被gzip_disable规则排除

# 5. 查看错误日志
tail -f /var/log/nginx/error.log

 

问题二:部分文件未压缩

 

# 常见原因:MIME类型不在gzip_types中

# 检查文件MIME类型
file --mime-type test.json
# application/json

# 检查Nginx的MIME配置
cat /etc/nginx/mime.types | grep json

# 确保gzip_types包含该类型
nginx -T | grep gzip_types

 

问题三:压缩后文件变大

 

# 小文件或高熵内容压缩后可能变大

# 检查原始文件大小
ls -la test.html

# 如果小于1KB,提高gzip_min_length
# 或者检查文件内容是否已压缩/随机数据

 

问题四:CPU占用过高

 

# 检查压缩级别
nginx -T | grep gzip_comp_level

# 查看Nginx进程CPU
top -p $(pgrep -d',' nginx)

# 解决方案:
# 1. 降低压缩级别
# 2. 使用预压缩
# 3. 增加gzip_min_length
# 4. 限制压缩类型

 

调试脚本

 

#!/bin/bash
# debug_gzip.sh - Gzip配置调试

URL=$1
if [ -z "$URL" ]; then
    echo"用法: $0 "
    exit 1
fi

echo"=== Gzip调试: $URL ==="
echo""

echo"--- 请求头 ---"
curl -sI "$URL" | head -20

echo""
echo"--- 带Accept-Encoding的请求 ---"
curl -sI -H "Accept-Encoding: gzip, deflate""$URL" | head -20

echo""
echo"--- 关键响应头 ---"
echo"Content-Encoding: $(curl -sI -H 'Accept-Encoding: gzip' "$URL" | grep -i content-encoding)"
echo"Content-Length (原始): $(curl -sI "$URL" | grep -i content-length)"
echo"Content-Length (压缩): $(curl -sI -H 'Accept-Encoding: gzip' "$URL" | grep -i content-length)"
echo"Vary: $(curl -sI -H 'Accept-Encoding: gzip' "$URL" | grep -i vary)"

echo""
echo"--- 内容类型 ---"
echo"Content-Type: $(curl -sI "$URL" | grep -i content-type)"

 

5.2 性能监控

Nginx状态监控

 

# 启用状态页
location /nginx_status {
    stub_status on;
    allow 127.0.0.1;
    deny all;
}

 

压缩率日志

 

# 记录压缩比例
log_format gzip_log '$remote_addr [$time_local] "$request" '
                    '$status $body_bytes_sent '
                    'gzip_ratio=$gzip_ratio '
                    'rt=$request_time';

access_log /var/log/nginx/gzip.log gzip_log;

 

分析脚本

 

#!/bin/bash
# analyze_gzip.sh - 分析Gzip压缩效果

LOG_FILE=${1:-/var/log/nginx/gzip.log}

echo"=== Gzip压缩效果分析 ==="
echo""

echo"--- 压缩比例分布 ---"
awk '{
    for(i=1;i<=NF;i++) {
        if($i ~ /gzip_ratio=/) {
            split($i, a, "=")
            ratio = a[2]
            if (ratio == "-") {
                none++
            } else if (ratio < 1.5) {
                low++
            } else if (ratio < 3) {
                medium++
            } else {
                high++
            }
        }
    }
}
END {
    total = none + low + medium + high
    printf "未压缩: %d (%.1f%%)
", none, none/total*100
    printf "低压缩(<1.5x): %d (%.1f%%)
", low, low/total*100
    printf "中压缩(1.5-3x): %d (%.1f%%)
", medium, medium/total*100
    printf "高压缩(>3x): %d (%.1f%%)
", high, high/total*100
}'$LOG_FILE

echo""
echo"--- 按文件类型统计 ---"
awk '{
    # 提取URL和压缩比
    url = $5
    gsub(/"/, "", url)
    for(i=1;i<=NF;i++) {
        if($i ~ /gzip_ratio=/) {
            split($i, a, "=")
            ratio = a[2]
        }
    }

    # 提取扩展名
    n = split(url, parts, ".")
    ext = parts[n]
    n = split(ext, parts, "?")
    ext = parts[1]

    if (ratio != "-" && ratio > 0) {
        count[ext]++
        sum[ext] += ratio
    }
}
END {
    printf "%-10s %10s %15s
", "类型", "请求数", "平均压缩比"
    for (ext in count) {
        printf "%-10s %10d %15.2f
", ext, count[ext], sum[ext]/count[ext]
    }
}'$LOG_FILE | sort -t$'	' -k2 -rn

 

Prometheus监控指标

 

# prometheus.yml 抓取配置
scrape_configs:
-job_name:'nginx'
    static_configs:
      -targets:['localhost:9113']

# 自定义指标(需要nginx-prometheus-exporter)
# nginx_http_requests_total
# nginx_connections_active
# nginx_connections_reading
# nginx_connections_writing

 

5.3 备份与恢复

配置备份

 

#!/bin/bash
# backup_gzip_config.sh

BACKUP_DIR="/backup/nginx/gzip"
DATE=$(date +%Y%m%d)

mkdir -p $BACKUP_DIR

# 备份gzip相关配置
nginx -T | grep -A 100 'gzip' > $BACKUP_DIR/gzip_config_$DATE.txt

# 备份完整配置
cp -r /etc/nginx/conf.d/ $BACKUP_DIR/conf.d_$DATE/

# 保留30天
find $BACKUP_DIR -mtime +30 -delete

echo"备份完成: $BACKUP_DIR"

 

快速回滚

 

#!/bin/bash
# rollback_gzip.sh - 回滚到默认gzip配置

cat > /etc/nginx/conf.d/gzip.conf << 'EOF'
# Gzip默认配置
gzip on;
gzip_comp_level 5;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript text/xml;
gzip_vary on;
EOF

nginx -t && nginx -s reload
echo "已回滚到默认gzip配置"

 

六、总结

6.1 技术要点回顾

Gzip压缩优化的核心就是这几点:

选对压缩级别:生产环境用5-6,别用9

选对压缩类型:只压缩文本类,别碰图片视频

用好预压缩:高频访问的静态资源必须预压缩

开启Vary头:gzip_vary on 必须有

统一入口压缩:在Nginx层统一处理,后端不压缩

关键配置速记:

 

gzip on;
gzip_comp_level 5;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript;
gzip_vary on;
gzip_static on;

 

6.2 进阶学习方向

Brotli压缩:比Gzip压缩率高15-20%,现代浏览器都支持

Zstd压缩:Facebook开源的新一代压缩算法

动态压缩级别:根据CPU负载动态调整压缩级别

边缘压缩:在CDN边缘节点进行压缩

6.3 参考资料

Nginx Gzip模块文档:https://nginx.org/en/docs/http/ngx_http_gzip_module.html

Gzip vs Brotli对比:https://www.keycdn.com/blog/brotli-compression

HTTP压缩机制RFC:https://tools.ietf.org/html/rfc7231#section-3.1.2.2

BREACH攻击说明:https://breachattack.com/

附录

A. 命令速查表

命令 说明
gzip -9 file.js 压缩文件(最高级别)
gzip -k file.js 压缩并保留原文件
gzip -l file.js.gz 查看压缩信息
gunzip file.js.gz 解压文件
zcat file.js.gz 查看压缩文件内容
curl -I -H "Accept-Encoding: gzip" URL 测试gzip是否生效

B. 配置参数详解

参数 默认值 说明
gzip off 开启/关闭gzip
gzip_comp_level 1 压缩级别1-9
gzip_min_length 20 最小压缩大小(字节)
gzip_buffers 32 4k 压缩缓冲区配置
gzip_types text/html 压缩的MIME类型
gzip_vary off 是否添加Vary头
gzip_proxied off 代理请求压缩策略
gzip_disable - 禁用压缩的User-Agent
gzip_http_version 1.1 启用压缩的最低HTTP版本
gzip_static off 静态预压缩开关

C. 术语表

术语 解释
Gzip GNU zip,一种基于DEFLATE算法的压缩格式
DEFLATE 结合LZ77和霍夫曼编码的压缩算法
Content-Encoding HTTP响应头,指示内容的编码方式
Accept-Encoding HTTP请求头,告知服务器客户端支持的编码
Vary HTTP响应头,指示缓存应根据哪些请求头区分响应
Transfer-Encoding 传输编码,chunked表示分块传输
MIME Type 多用途互联网邮件扩展类型,标识内容格式
Brotli Google开发的新一代压缩算法,压缩率优于Gzip

 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分