nginx全链路压缩需区分响应压缩(原生支持gzip/brotli)与请求体解压(需lua或上游服务配合);响应端依accept-encoding协商选择br优先、gzip兜底,请求端不原生支持解压,须通过lua-zlib或后端中间件处理。

通过 Nginx 实现请求的全链路压缩,核心是同时对 客户端发来的请求体(Request Body) 和 Nginx 返回给客户端的响应体(Response Body) 进行压缩处理。但需注意:Nginx 本身不原生支持请求体解压,需借助第三方模块或上游服务配合;而响应压缩则开箱即用。下面分场景说明可行方案和关键配置。
响应压缩:启用 gzip / brotli 压缩输出
这是最常用、最稳定的部分。Nginx 可自动压缩响应内容(如 HTML、JSON、JS、CSS),前提是客户端声明支持(Accept-Encoding 头包含 gzip 或 br)。
- 启用 gzip 压缩(推荐基础兼容性):
gzip on; gzip_types application/json text/plain text/css application/javascript text/xml application/xml application/xml+rss text/javascript; gzip_min_length 1000; gzip_comp_level 6; gzip_vary on; gzip_proxied any;
- 启用更高效的 Brotli 压缩(需编译时添加
ngx_brotli模块):
brotli on; brotli_types application/json text/plain text/css application/javascript; brotli_comp_level 4;
注意:gzip_vary on 会让 Nginx 添加 Vary: Accept-Encoding 响应头,确保 CDN 或代理能正确缓存不同编码版本。
请求体解压:需上游服务或 Lua 脚本介入
Nginx 官方模块不解析或解压请求体(如客户端用 Content-Encoding: gzip 发送压缩的 JSON)。若后端服务(如 Node.js、Python Flask)无法直接处理压缩请求体,就必须在 Nginx 层“提前解压”。
- 方案一:使用
nginx-http-lua-module+lua-zlib - 方案二:改由上游应用层统一处理(更推荐)——让后端服务自行解压请求体
若必须由 Nginx 承担,可参考 Lua 示例逻辑(需开启 Lua 支持):
location /api/ {
access_by_lua_block {
local zlib = require "zlib"
local encoding = ngx.var.http_content_encoding
if encoding == "gzip" or encoding == "deflate" then
local body = ngx.req.get_body_data()
if body then
local ok, decompressed = pcall(zlib.inflate(), body)
if ok then
ngx.req.set_body_data(decompressed)
ngx.req.clear_header("Content-Encoding")
ngx.req.set_header("Content-Length", #decompressed)
end
end
end
}
proxy_pass http://backend;
}
⚠️ 注意:该方式有性能开销,且不支持流式解压大请求体;生产环境建议优先由后端框架(如 Express 的 compression 中间件、FastAPI 的 GZipMiddleware)处理请求解压。
全链路协同的关键:Header 与协议一致性
真正实现“全链路”压缩效果,依赖各环节明确协商与传递压缩意图:
- 客户端发送请求时,需设置
Content-Encoding: gzip(请求体压缩)和Accept-Encoding: gzip, br(期望响应压缩) - Nginx 若解压了请求体,务必清除
Content-Encoding并重置Content-Length,避免后端误判 - 若 Nginx 后接另一层代理(如 Kubernetes Ingress),需确认其未覆盖或禁用压缩头
- 对
POST/PUT等含 body 的方法才考虑请求压缩;GET请求无 body,无需处理请求解压
验证与调试技巧
快速确认是否生效:
- 响应压缩:用
curl -H "Accept-Encoding: gzip" -I https://yoursite/api查看返回头是否有Content-Encoding: gzip - 请求压缩:用
curl -H "Content-Encoding: gzip" --data-binary @compressed.json -H "Content-Type: application/json" https://yoursite/api,观察后端是否收到明文 - Nginx 日志中添加
$sent_http_content_encoding和$request_completion字段辅助排查
不复杂但容易忽略:压缩不是越高压越好。过高的 gzip_comp_level(如 9)会显著增加 CPU 开销,一般 4–6 是平衡点;Brotli 级别 4–6 同理。











