如果上游启动,Nginx 绕过缓存,如果关闭则使用缓存

Posted

技术标签:

【中文标题】如果上游启动,Nginx 绕过缓存,如果关闭则使用缓存【英文标题】:Nginx bypass cache if upstream is up and use cache if down 【发布时间】:2019-02-10 20:49:26 【问题描述】:

如果上游启动(max-age 1)绕过缓存,如果关闭(proxy_cache_use_stale)使用缓存,我创建了以下配置:

proxy_cache_path   /app/cache/ui levels=1:2 keys_zone=ui:10m max_size=1g inactive=30d;
server 
    ...
    location /app/ui/config.json 
        proxy_cache ui;
        proxy_cache_valid 1d;
        proxy_ignore_headers Expires;           
        proxy_hide_header Expires;
        proxy_hide_header Cache-Control;
        add_header Cache-Control "max-age=1, public";
        proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
        add_header X-Cache-Status $upstream_cache_status;
        add_header X-Cache-Date $upstream_http_date;
        proxy_pass http://app/config.json;
    

但是当上游关闭并且客户端仅获得 504 网关超时时不使用缓存。我已经阅读了以下文章:

https://nginx.org/ru/docs/http/ngx_http_proxy_module.html#proxy_cache_use_stale

How to configure NginX to serve Cached Content only when Backend is down (5xx Resp. Codes)?

https://serverfault.com/questions/752838/nginx-use-proxy-cache-if-backend-is-down

而且它不像我预期的那样工作。任何帮助表示赞赏。

【问题讨论】:

【参考方案1】:

与链接到的其他类似问题一样,这是XY Problem 的示例。

用户想要做 X,错误地认为解决方案是 Y,但不能做 Y,因此寻求关于如何做 Y 的帮助,而不是实际询问 X。这总是会给那些试图给出答案的人带来问题。

在这种情况下,实际问题 X 似乎是您希望对后端进行故障转移,但希望避免在单独的服务器实例上花钱,并想知道有哪些可用选项。

为此使用缓存的想法并没有完全取消,但您必须像故障转移服务器一样接近和设置缓存,这意味着它必须是一个完全独立于后端的系统。这排除了与后端密切相关的proxy_cache

在您的情况下,我将设置一个 memcached 服务器并将其配置为缓存您的内容,但通常不处理您的请求,除非出现 50 倍错误。

Nginx 附带一个memcached module,可以编译和使用,但它没有向 memcached 添加项目的功能。您必须在 Nginx 之外执行此操作(通常在您的后端应用程序中)。

设置 memcached 的指南 can be found here 或只是进行网络搜索。一旦启动并运行,这将在 Nginx 方面为您工作:

server 
    location / 
        # You will need to add items to memcached yourself here
        proxy_pass             http://backend;
        proxy_intercept_errors on
        error_page             502 504 = @failover;
    

    location @failover 
        # Assumes memcached is running on Port 11211
        set            $memcached_key "$uri?$args";
        memcached_pass host:11211;
    
      

比有限的标准 memcached 模块好得多的是来自 OpenResty 的 3rd party memc module,它允许您直接在 Nginx 中添加内容。

OpenResty 还有非常灵活的lua-resty-memcached,这实际上是最好的选择。

对于这两种情况,您都需要将它们编译到您的 Nginx 中并熟悉如何设置它们。如果您需要这方面的帮助,请在此处使用 OpenResty 标签提出新问题或尝试使用 OpenResty 支持系统。

总结

    您真正需要的是故障转移服务器。 这必须独立于后端。 您可以像这样使用缓存系统,但它不能是proxy_cache如果您无法忍受在最短 1 秒的时间内获取缓存结果。 您需要扩展一个典型的 Nginx 安装来执行此操作。

【讨论】:

感谢您的回答,但我仍然有一个问题,初始配置有什么问题以及为什么它不起作用。【参考方案2】:

让我们讨论一个非常简单的两台服务器设置。一个正在运行的 apache2 服务于一个简单的 html 页面。另一个正在运行的 nginx 反向代理到第一个。

http 
[...]

  proxy_cache_path /var/lib/nginx/tmp/proxy levels=2:2 keys_zone=one:10m inactive=48h max_size=16g use_temp_path=off;

  upstream backend 
    server foo.com;
  

  server 
  [...]
    location / 
      proxy_cache           one;
      proxy_cache_valid     200 1s;
      proxy_cache_lock      on;

      proxy_connect_timeout 1s;
      proxy_cache_use_stale error timeout updating http_502 http_503 http_504;

      proxy_pass http://backend/
    
  

此设置对我有用。最重要的区别是proxy_cache_valid 200 1s;,这意味着只有http代码为200的响应才会被缓存,并且只会在1秒内有效。这确实意味着对某个资源的第一个请求将从后端获取并放入缓存中。对同一资源的任何进一步请求都将从缓存中提供一整秒。之后,第一个请求将再次转到后端,等等。

proxy_cache_use_stale 是场景中的重要部分。它基本上说明了在哪些情况下它仍应为缓存版本提供服务,尽管proxy_cache_valid 指定的时间已经过去。所以在这里你必须决定在哪些情况下你仍然想从缓存中提供服务。

The directive's parameters are the same as for proxy_next_upstream.

您将需要这些:

error:如果服务器仍然启动,但没有响应,或者没有正确响应。

timeout:连接服务器,请求或响应超时。这也是为什么要将proxy_connect_timeout 设置为低的原因。默认值为 60 秒,对于最终用户来说是很长的时间。

updating: 已经有新内容的请求正在处理中。 (不是真的需要,但从性能的角度来看更好。)

http_xxx 参数对您没有多大用处,当后端服务器关闭时,您将永远不会收到包含任何这些代码的响应。

在我的现实生活中,后端服务器也是 nginx,它代理到本地主机上的不同端口。因此,当 nginx 运行良好,但其中任何一个后端出现故障时,参数 http_502http_503http_504 就不再有用了,因为这些正是我将收到的 http 代码。

http_403http_404http_500 我不想从缓存中提供服务。当文件被禁止(403)或不再在后端(404)或脚本出错(500)时,这是有原因的。但这是我的看法。

【讨论】:

proxy_connect_timeoutproxy_cache_use_stale timeout 帮助了我,现在我得到了我最初想要的东西。非常感谢!【参考方案3】:

它不工作,因为 http_500、http_502、http_503、http_504 代码需要来自后端。在您的情况下,504 是 nginx 代码。 所以你需要具备以下条件:

proxy_connect_timeout 10s;
proxy_cache_use_stale ... timeout ...

proxy_cache_use_stale ... updating ...

或两者兼而有之。

【讨论】:

以上是关于如果上游启动,Nginx 绕过缓存,如果关闭则使用缓存的主要内容,如果未能解决你的问题,请参考以下文章

如果未找到上游主机,则设置 nginx 不会崩溃

如果配置文件中的多个站点之一无法解析,nginx 将无法启动。 “在上游找不到主机”

nginx怎样告诉搜索引擎网站已永久关闭

Nginx 减轻缓存失效对上游服务压力 proxy_cahce_lock和proxy_cache_use_stale

AWS Nginx“从上游读取响应标头时上游过早关闭连接”

Nginx上游过早关闭连接,同时从上游读取响应标头,用于大型请求