精通 Nginx 压缩:Gzip 与 Brotli 提升网站性能

通过对比 Gzip 和 Brotli 算法,掌握 Nginx 内容压缩。学习启用两者的实用配置指令,了解性能权衡,并发现最佳实践,例如使用静态 Brotli 文件来大幅减少带宽使用并加速 Web 服务器上的内容交付。

精通 Nginx 压缩:Gzip 与 Brotli 提升网站性能

Nginx 压缩是一种看似微小,但一旦查看网络面板便会发现其巨大影响的优化。一个 CSS 文件、JavaScript 包、HTML 页面、JSON API 响应或 SVG 文件,在网络上传输时体积可以大大缩小,然后在浏览器中再解压回原始内容。

实际的选择通常不是“永远只用 Gzip 或 Brotli”。大多数生产环境会同时使用两者:Brotli 用于支持它的浏览器,Gzip 作为回退方案,以及构建管道可以预先创建的预压缩静态文件。不过,细节很重要。一个复制粘贴的压缩块可能会浪费 CPU、跳过重要的 MIME 类型,或者因为 Brotli 模块实际上并未安装而静默失败。

理解 Nginx 中的 Web 压缩

压缩的工作原理是查找数据(如 HTML、CSS 或 JavaScript 文件)中的重复模式,并用较短的引用替换它们。这减少了通过网络传输的文件总大小。Nginx 作为中间层,在将数据发送到浏览器之前动态应用所选的压缩算法。

Nginx 通常需要 ngx_http_gzip_module 模块用于 Gzip,以及一个单独的 Brotli 模块用于 Brotli。大多数常见的 Nginx 包都包含 Gzip 支持。Brotli 则更不固定:一些发行版将其打包为动态模块,一些第三方仓库包含它,而一些构建版本则根本没有它。

前提条件

如果你计划使用 Brotli,请确保你的 Nginx 安装支持它。你可以通过运行以下命令来检查 Brotli 是否可用:

nginx -V 2>&1 | grep -i brotli

如果输出提到了 Brotli,请确认它是编译进二进制文件还是作为动态模块加载的。在 Debian 或 Ubuntu 系统上,如果你的包使用动态模块,还要检查 /etc/nginx/modules-enabled/ 下的文件:

ls -l /etc/nginx/modules-enabled/ | grep -i brotli

如果在 nginx -t 期间 Nginx 拒绝 brotli on;,则该模块对该正在运行的 Nginx 二进制文件不可用,即使操作系统在其他地方安装了 Brotli 包。

1. 配置 Gzip 压缩

Gzip 是内容压缩的成熟且广泛支持的标准。它在压缩比和 CPU 开销之间提供了良好的平衡。

在 Nginx 配置中启用 Gzip

Gzip 设置通常放在 Nginx 配置文件(nginx.conf 或包含的配置文件)的 httpserverlocation 块中。

要启用 Gzip 压缩,请使用以下指令:

http {
    # 启用 Gzip 压缩
    gzip on;

    # 设置要压缩的最小响应大小(字节)
    # 仅压缩大于 1000 字节的文件
    gzip_min_length 1000;

    # 压缩级别(1=最快/最低压缩率,9=最慢/最高压缩率)
    gzip_comp_level 6;

    # 指定要压缩的 MIME 类型
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;

    # 推荐:发送 Vary: Accept-Encoding 标头,以便代理缓存压缩和未压缩版本
    gzip_vary on;

    # 推荐:添加 gzip 标头以进行标识
    gzip_proxied any;
}

关键 Gzip 指令说明

  • gzip on;:激活 Gzip 模块。
  • gzip_comp_level:将其设置在 4 到 6 之间通常是性能的最佳点。更高的级别可以节省更多带宽,但会增加服务器上的 CPU 使用率。
  • gzip_types:至关重要的是,你绝不应该压缩已经压缩过的格式,如图像(.jpg.png.gif)或视频。

2. 配置 Brotli 压缩

Brotli 是 Google 开发的一种较新的压缩算法。对于文本资源,它通常产生比 Gzip 更小的文件。确切收益取决于内容、压缩级别以及文件是在每次请求时压缩还是在部署期间提前压缩。

在 Nginx 配置中启用 Brotli

Brotli 配置使用类似的指令,但将 gzip 替换为 brotli

brotli on;
brotli_comp_level 6; # 通常推荐 4 到 8
brotli_static on; # 如果可用,启用提供预压缩的 .br 文件
brotli_types text/plain text/css application/json application/javascript application/x-javascript text/xml;

关于预压缩 (brotli_static) 的重要说明:

Brotli 压缩在每次请求时动态执行可能会非常消耗 CPU。一个常见的做法是使用专用的离线工具(如 brotli 命令行工具)预压缩资源,并将 .br 版本与原始文件一起存储(例如,style.cssstyle.css.br)。

设置 brotli_static on; 告诉 Nginx 检查请求的资源是否存在预压缩的 .br 文件,如果客户端支持 Brotli,则直接提供该文件,完全绕过实时处理。

3. Gzip 与 Brotli:做出正确选择

在 Gzip 和 Brotli 之间做出选择很大程度上取决于客户端支持情况和你的服务器资源。

特性 Gzip Brotli 建议
压缩率 良好 通常对文本资源更好 Brotli 通常胜出
CPU 负载(动态) 中到高 Gzip 更轻量
客户端支持 几乎通用(所有现代浏览器) 非常高(大多数现代浏览器) Gzip 对于旧版支持更安全
预压缩 可能,但不太常见 强烈推荐 (brotli_static) 如果可能,使用 Brotli 预压缩

混合方法:最佳实践

最健壮的现代配置使用混合设置,优先为现代客户端使用 Brotli,同时提供 Gzip 作为可靠的备选方案。

  1. 优先使用 Brotli: 首先配置 Brotli,通常使用 brotli_static on; 以提高速度。
  2. 回退到 Gzip: 确保启用 Gzip 并配置为处理不支持 Brotli 的客户端。

Nginx 根据客户端的 Accept-Encoding 标头和构建中启用的模块来选择响应。在正常的浏览器流量中,当客户端声明支持 br 时,Brotli 是首选;对于只请求 gzip 的客户端、工具、代理和旧堆栈,Gzip 仍然有用。

混合配置示例

如果你的 Nginx 版本同时支持这两个模块,你可以同时启用它们。Nginx 根据客户端的请求标头优先选择哪个模块提供内容。

http {
    # --- Brotli 配置 ---
    brotli on;
    brotli_comp_level 6;
    brotli_static on;
    brotli_types
        text/plain
        text/css
        application/javascript
        application/json
        application/xml
        image/svg+xml;

    # --- Gzip 配置(回退) ---
    gzip on;
    gzip_comp_level 5;
    gzip_vary on;
    gzip_proxied any;
    gzip_types
        text/plain
        text/css
        application/javascript
        application/json
        application/xml
        image/svg+xml;
}

性能调优技巧

无论你选择哪种算法,请遵循以下最佳实践以获得最大效果:

1. 验证实际响应

不要因为配置文件中包含 gzip on;brotli on; 就认为压缩正在工作。检查实际响应:

curl -I -H 'Accept-Encoding: br,gzip' https://example.com/app.js
curl -I -H 'Accept-Encoding: gzip' https://example.com/app.js

查找 Content-Encoding: brContent-Encoding: gzip。同时,确保可能被 CDN 或共享代理缓存的响应上保留 Vary: Accept-Encoding 标头,以免压缩和未压缩的版本混淆。

2. 避免过度压缩

除非你的服务器严重未充分利用,否则切勿将 gzip_comp_levelbrotli_comp_level 设置得太高(例如 9 或 11)。文件大小减少的边际收益很少能证明计算所需的额外 CPU 周期是合理的。

3. 缓存预压缩文件

对于 Brotli,使用 brotli_static on; 并预压缩你的静态资源是最大的性能提升。这将 CPU 负载从请求时间转移到部署时间。

4. 测试你的配置

修改 Nginx 配置后,在重新加载之前始终测试语法:

sudo nginx -t

如果成功,重新加载 Nginx 以应用更改:

sudo systemctl reload nginx

你还可以使用浏览器开发者工具或性能测试服务来确认响应是否以 Content-Encoding: gzipContent-Encoding: br 提供。

实际部署方式

如果网站完全没有压缩,请从 Gzip 开始。它内置于大多数 Nginx 包中,可以让你快速获得基准。然后,在确认模块支持并有办法在部署期间为静态资源生成 .br 文件后,再添加 Brotli。

对于 React、Vue 或静态文档站点,最佳设置通常是为构建的资源提供预压缩的 .br.gz 文件,为 HTML 和 API 响应提供适度的动态压缩,以及一个尊重 Accept-Encoding 的 CDN 配置。对于接近 CPU 限制运行的小型 API,保守的 Gzip 级别可能是更好的第一步。

胜利不仅仅是文件更小。良好的压缩可以保持较低的带宽,帮助较慢的客户端连接,并在不更改应用程序代码的情况下消除不必要的传输时间。主要的纪律是测试标头,避免压缩已经压缩的媒体,并保持压缩级别足够“平淡”,以便你的服务器在流量高峰期间仍能正常运转。