为了在部署期间显示维护页面,我一直在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
if (-f /home/shared/system/maintenance.html) { return 503; }
此规则支持命名位置
location @maintenance
,并在一切正常的情况下共同重定向到/maintenance.html
root /home/shared/errors
。 -
此页面包含和图像
some.jpg
- 要接收此图像浏览器,请启动新请求,此新请求再次命中规则 #1所有这些都在最初的问题中进行了描述,但是
如果我使用一些
if
魔法,例如弗兰克·法默的答案,我可以将服务器指向请求的文件,但 HTTP 答案将是 503 和浏览器(在我的测试中,除了 Safari 之外的所有浏览器)在调试控制台中抛出错误并确实显示图像但不处理 CSS 文件在相同情况下。这很关键。
-
我试图为我的新内容请求使用位置魔术来解决这个问题 - 这意味着我必须:
-
不要
return 503
内容请求,根本不跳过命名位置。 -
请更改
root /home/shared/errors
因为维护内容仍然存在。
-
-
最后,我有下一个解决方案:
-
为
maintenance.html
maintenance-static
文件和维护静态样式表中的所有静态内容和更改路径创建文件夹 -
接下来使用这些规则(我相信它们是自我描述的),这些规则取代了初始问题中的单个
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;
}
我知道,它在正常情况下会创建不必要的/维护位置,但您可以想象另一个位置路径,您的用户永远不会猜:)。