Nginx:缓存 Brotli 压缩代理上游响应

Nginx: cache Brotli compressed proxied upstream responses

我在 Nginx 中为动态生成但很少更改的资源启用了 Brotli 压缩。

我的预期是,当Nginx缓存上游响应时,它也会缓存压缩结果。因此,我假设启用 Brotli 的 CPU 成本可以忽略不计。相反,我看到 perf top 确认与 Brotli 有关的性能影响。

我确认缓存到上游服务器有效。但是,Nginx 仅在其缓存中存储未压缩的上游请求。因此,它必须 运行 为每个请求进行昂贵的 Brotli 压缩。就是这个问题。

有资源(与 gzip 压缩相关)建议在上游进行压缩,或者如果这不是创建第二个 Nginx 来代理请求的选项,它将充当上游的角色并进行压缩。两种解决方案都不是很优雅。

有没有办法让Nginx不仅缓存未压缩的上游请求,还缓存压缩的结果?

也许我忽略了一些。这是一个简化的配置:

proxy_cache_path /var/cache/nginx levels=1 keys_zone=my_config_cache:8M
                 inactive=60m use_temp_path=off;

server {
  location = /foo {

    proxy_pass http://test-upstream;
    proxy_http_version 1.1;
    proxy_set_header Connection "";

    proxy_ignore_headers Expires;
    proxy_ignore_headers Cache-Control;

    brotli on;
    brotli_comp_level 11;

    proxy_cache my_config_cache;
    proxy_cache_valid 10s;
    proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;

    expires 60s;
  }
}

brotli_comp_level 11;

太高了。对于动态内容,建议 4

您不能用当前设置做您想做的事。

如果你可以将上游设置为brotli-capable,那么你可以通过将$http_accept_encoding作为一部分来缓存来自它的压缩响应的缓存键。但是,仅此一点还不够好,因为您必须规范化它的值(想想,所有可能的 Accept-Encoding 传入 headers,将导致臃肿且效率极低的缓存)。

如果你真的关心支持 Brotli 的客户端(现在大多数浏览器都支持 Brotli),以及可能的最高压缩级别,那么你可以 通过提供 Accept-Encoding: br 而 proxy-passing 来强制对 brotli-capable 上游进行压缩,这将导致缓存始终具有 brotli 编码的响应。 (你不需要调整你的缓存键)。但是,这需要一个功能,目前不可用,例如我称之为unbrotli

想法是一切都向上游说 "I want Brotli encoded response"。上游提供 Brotli-ed 响应(当然,在适用的情况下,例如对于文本响应)。但对于只支持 gzip 或根本不支持压缩的客户端,应该从 Brotli 中动态解压(非常低 CPU 影响)。这不是很好,但是 Brotli 无能力的客户数量正在减少。