nginx维护页面存在内容问题



为了在部署期间显示维护页面,我一直在nginx中使用下一个配置:

if (-f /home/shared/system/maintenance.html) {
    return 503;
}
error_page 503 @maintenance;
location @maintenance {
    root /home/shared/errors;
    rewrite ^(.*)$ /maintenance.html break;
}

一切都很好,直到我需要将静态内容添加到维护页面(图像、样式表等)

没有静态内容错误地处理此类日志.log:

2011/05/05 02:47:20 [notice] 13760#0: *6 "^(.*)$" matches "/some.jpg", client: x.x.x.x, server: server.com, request: "GET /some.jpg HTTP/1.1", host: "server.com"
2011/05/05 02:47:20 [notice] 13760#0: *6 rewritten data: "/maintenance.html", args: "", client: x.x.x.x, server: server.com, request: "GET /some.jpg 2 HTTP/1.1", host: "server.com"

这是合乎逻辑的 - 如果我确实将所有内容重写为维护.html这意味着静态内容不是排除。

但是我找不到任何适当的解决方案来重定向到每个文件,除了物理存在于root /home/shared/errors文件夹中的文件。

附言。 /home/shared/errors 不与公共项目文件夹共享任何资源 - 这是完全独立的文件夹(即使没有任何指向项目/current的符号链接)。

对不起,弗兰克·法默,但这行不通。

什么有效但不那么整洁:

以及请求如何工作 ->

  1. 我使用规则#1

    if (-f /home/shared/system/maintenance.html) {
        return 503;
    }
    

    此规则支持命名位置location @maintenance,并在一切正常的情况下共同重定向到/maintenance.html root /home/shared/errors

  2. 此页面包含和图像some.jpg - 要接收此图像浏览器,请启动新请求,此新请求再次命中规则 #1

    所有这些都在最初的问题中进行了描述,但是

    如果我使用一些if魔法,例如弗兰克·法默的答案,我可以将服务器指向请求的文件,但 HTTP 答案将是 503 和浏览器(在我的测试中,除了 Safari 之外的所有浏览器)在调试控制台中抛出错误并确实显示图像但不处理 CSS 文件在相同情况下。

    这很关键。

  3. 我试图为我的新内容请求使用位置魔术来解决这个问题 - 这意味着我必须:

    1. 不要return 503内容请求,根本不跳过命名位置。

    2. 请更改root /home/shared/errors因为维护内容仍然存在。

  4. 最后,我有下一个解决方案:

    1. maintenance.html maintenance-static文件和维护静态样式表中的所有静态内容和更改路径创建文件夹

    2. 接下来使用这些规则(我相信它们是自我描述的),这些规则取代了初始问题中的单个if (-f /home/shared/system/maintenance.html)

      set $can503 0;
      if (-f /home/shared/system/maintenance.html) {
          set $can503 1;
      }
      if ($uri ~* /maintenance-static/) {
          set $can503 0;
      }
      location /maintenance-static/ {
          root /home/shared/errors;
      }
      if ($can503 = 1) {
         return 503;
      }
      

该解决方案在所有浏览器中和shared/errors文件夹中的大量页面中没有任何错误,例如维护.html,错误.html,过载.html等。

这个解决方案不是很清楚 - 也许你可以提示我如何让它更整洁,但请记住我们正在处理单独的请求(以及在高负载的情况下每个文件/请求的单独 nginx 进程等)对于初始 html 及其内容我们不能对所有文件使用相同的规则进行 503 重定向。

我花了两个小时寻找这个问题的答案,终于找到了这篇文章。 似乎应该更常见。我的解决方案介于弗兰克和威尔之间。正如Wile所说,某些浏览器(例如Chrome)将选择不呈现返回503的任何文件的CSS/JS,即使它完全正确地获取了它们。

但是有一个修复程序比Wile所做的更不黑客。只需返回 200!

我的完整解决方案如下:

error_page 503 @maintenance;
location @maintenance {
    root /path_to_static_root;
    if (!-f $request_filename) {
        rewrite ^(.*)$ /rest_of_path/maintenance.html break;
    }
    return 200;
}

像魅力一样工作。 :)

location @maintenance {
    root /home/shared/errors;
    rewrite  (some.jpg|some2.gif)$ /$1 break;
    rewrite ^(.*)$ /maintenance.html break;
}

这可能在不枚举列入白名单的文件的情况下起作用:

location @maintenance {
    root /home/shared/errors;
    if (!-f $request_filename) {
        rewrite ^(.*)$ /maintenance.html break;
    }
}

此解决方案仅适用于单个 if 语句,并且更具可读性和可理解性:

upstream unicorn {
        server unix:/path/to/unicorn.sock;
}
server {
        listen 3000 default deferred;
        proxy_read_timeout 3600;
        client_max_body_size 4G;
        set_real_ip_from 0.0.0.0/0;
        root /path/to/current/public;
        try_files $uri/index.html $uri.html $uri @unicorn;
        error_page 404 /404.html;
        error_page 500 502 504 /500.html;
        error_page 503 /system/maintenance.html;
        location /404.html {
                internal;
        }
        location /500.html {
                internal;
        }
        location @unicorn {
                if (-f $document_root/system/maintenance.html) {
                        return 503;
                }
                proxy_set_header Host $http_host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
                proxy_redirect off;
                proxy_pass http://unicorn;
        }
}
server {
    listen 80;
    server_name myserv.trunk;
    autoindex off;
    access_log /var/log/nginx/sitename-access.log;
    location ^~ /static/ {
       root /home/dev/myserv-site/;
    }
    location ~ /(?P<language>en)?/? {
        uwsgi_pass unix:///tmp/uwsgi.sock;
        include uwsgi_params;
        error_page 502 @fallback;
        error_page 503 @maintenance;
        if (-f /home/dev/myserv-site/maintenance.active) {
          return 503;
        }
    }
    location @fallback {
      root /home/dev/myserv-site/;
      if ($language) {
          rewrite ^(?!/static/)(.*)$ /static/html/502.$language.html break;
      }
      rewrite ^(?!/static/)(.*)$ /static/html/502.zh.html break;
    }
    location @maintenance {
      root /home/dev/myserv-site/;
      if ($language) {
          rewrite ^(?!/static/)(.*)$ /static/html/503.$language.html;
      }
      rewrite ^(?!/static/)(.*)$ /static/html/503.zh.html break;
   }
}

以下是可翻译维护 (503) 或 502 错误页面屏幕的示例。如果用户转到 http://site.com/en/将显示英文页面(当维护.活动文件存在时)。静态目录位于 Myserv-Site Dir 中。

我尝试了上面的所有建议,不幸的是它们没有按预期工作。唯一对我有用的解决方案如下:

location / {
    if (-f /path/to/file/indicating/maintenance/mode) {
       rewrite ^(.+)$ /maintenance/$1;
    }
    #... the rest of the "normal" logic
}
location /maintenance {
    root /path/where/your/maintenance/root/is;
    rewrite ^/maintenance/(.*)$ /$1 break;
    try_files /$uri /index.html =404;
    return 200;
}

我知道,它在正常情况下会创建不必要的/维护位置,但您可以想象另一个位置路径,您的用户永远不会猜:)。

相关内容

  • 没有找到相关文章

最新更新