目录
3. proxy_next_upstream_timeout
1.上游出现失败时的容错方案
Nginx作为代理服务器与上游服务连接以及传输数据时,只要上游服务器没有向客户端发送一个字节,
就可以认定某些上游的响应是有问题的,此时代理服务器可以重新选择另外一个上游服务器作为服务器
对这个请求作出响应,之后代理服务器再将这个服务器的响应传给客户端,从而使得客户端没有感知到
后面有服务器其实已经不工作的这个事件的,这个功能对于Nginx作为一个集群的代理服务器用来容纳
一些出错的上游服务来说是非常有效的.
"【Nginx】反向代理流程一"文中提到的proxy_next_upstream以及本文中的
proxy_next_upstream_timeout
proxy_next_upstream_tries
指令都可以对反向代理过程中上游出现失败时进行一定的设置和处理.
http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream
http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream_timeout
http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream_tries
http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_intercept_errors
2. proxy_next_upstream
官方的手册:
Syntax: proxy_next_upstream error | timeout | invalid_header
| http_500 | http_502 | http_503 | http_504 | http_403
| http_404 | http_429 | non_idempotent | off ...;
Default:proxy_next_upstream error timeout;
Context:http, server, location
Specifies in which cases a request should be passed to the next server:
error
an error occurred while establishing a connection with the server, passing a request to
it, or reading the response header;
timeout
a timeout has occurred while establishing a connection with the server, passing a
request to it, or reading the response header;
invalid_header
a server returned an empty or invalid response;
http_500
a server returned a response with the code 500;
http_502
a server returned a response with the code 502;
http_503
a server returned a response with the code 503;
http_504
a server returned a response with the code 504;
http_403
a server returned a response with the code 403;
http_404
a server returned a response with the code 404;
http_429
a server returned a response with the code 429 (1.11.13);
non_idempotent
normally, requests with a non-idempotent method (POST, LOCK, PATCH) are not passed to
the next server if a request has been sent to an upstream server (1.9.13); enabling this
option explicitly allows retrying such requests;
off
disables passing a request to the next server.
One should bear in mind that passing a request to the next server is only possible if
nothing has been sent to a client yet. That is, if an error or timeout occurs in the
middle of the transferring of a response, fixing this is impossible.
The directive also defines what is considered an unsuccessful attempt of communication
with a server. The cases of error, timeout and invalid_header are always considered
unsuccessful attempts, even if they are not specified in the directive. The cases of
http_500, http_502, http_503, http_504, and http_429 are considered unsuccessful
attempts only if they are specified in the directive. The cases of http_403 and http_404
are never considered unsuccessful attempts.
Passing a request to the next server can be limited by the number of tries and by time.
中文理解:
当上游返回出错的时候,我们可以用proxy_next_upstream这个指令来进行容错处理.
上下文是http, server, location.
这个指令生效的前提是没有向客户端发生任何内容,只要上游服务器向客户端发送哪怕是一个字节,都
说明这个上游服务已经生效了,就不能再选择一个新的上游服务了,所以一定是在接收到并开始转发一
个字节之前Nginx判断为错误,这个功能才能生效.
proxy_next_upstream这个指令后面可以跟很多不同的参数,如官方文档提供的那些:
error--只要出现错误,error都可以满足这样的场景,这个错误主要指网络错误,如TCP和IP层的错误
timeout--超时,分为连接超时,读超时,写超时,当出现这些场景的时候,可以执行重选另一个上游服务
invalid_header--表示收到的上游服务器的header是不合法的
http_500--上游服务器返回500
http_502--上游服务器返回502
http_503--上游服务器返回503
http_504--上游服务器返回504
http_403--上游服务器返回403
http_404--上游服务器返回404
http_429--上游服务器返回429
non_idempotent--normally, requests with a non-idempotent method (POST, LOCK, PATCH) are
not passed to the next server if a request has been sent to an upstream server (1.9.13);
enabling this option explicitly allows retrying such requests;
通常来说,含有POST, LOCK, PATCH这类非幂等方法的请求在已经发送给上游服务器的情况下是不能够
再向另一个上游服务器发送这样的请求的,但是如果设置了这个指令,就明确指出可以将已经发送给一
个上游服务器的请求发送给另一个上游服务器.
off--关闭proxy_next_upstream这个功能
3. proxy_next_upstream_timeout
Syntax: proxy_next_upstream_timeout time;
Default:
proxy_next_upstream_timeout 0;
Context: http, server, location
This directive appeared in version 1.7.5.
Limits the time during which a request can be passed to the next server.
The 0 value turns off this limitation.
4. proxy_next_upstream_tries
Syntax: proxy_next_upstream_tries number;
Default:
proxy_next_upstream_tries 0;
Context: http, server, location
This directive appeared in version 1.7.5.
Limits the number of possible tries for passing a request to the next server.
The 0 value turns off this limitation.
5.proxy_intercept_errors
http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_intercept_errors
官方手册:
Syntax: proxy_intercept_errors on | off;
Default:proxy_intercept_errors off;
Context:http, server, location
Determines whether proxied responses with codes greater than or equal to 300 should be
passed to a client or be intercepted and redirected to nginx for processing with the
error_page directive.
功能:
用error_page拦截并重新定义上游失败响应的内容
中文理解:
决定了上游服务器返回大于等于300的返回码时返回信息是直接返回给客户端还是返回给代理服务器Nginx
用error_page命令去处理这个错误码再返回给客户端.
6.测试案例
测试步骤:
(1)开始的时候,一台代理服务器(端口8080),两台上游服务器(第一个上游服务器
端口是8081,第二个上游服务器端口是8082),代理服务器采用Round-Robin
算法,代理服务器中相关的容错配置是“proxy_next_upstream off”,
curl 127.0.0.1:8080/error可以发现两台服务器是正常地轮流提供服务的;
(2)之后将第二个上游服务器的端口改了并reload,再去用curl 127.0.0.1:8080/error测试,
此时轮到访问第二个服务器的时候,报错"502 Bad Gateway",此时已经
连接不上第二个上游服务器了,由于容错配置的是“proxy_next_upstream off”,
直接将报错信息返回给客户端;
(3)将代理服务器中相关的容错配置改成“proxy_next_upstream error”并reload,
可以发现,虽然我们仍然用的Round-Robin算法(上游两台服务器应该轮流访问),
但是每次我们总是能获取到返回值的,因为访问第二个上游服务器的时候失败
导致proxy_next_upstream生效,于是重新改用第一个服务器来为用户提供服务,
这个功能可以使得Nginx把错误屏蔽,这是分布式集群下非常好用的一个功能.
只要还有上游服务能工作,客户端就能得到服务.
(4)将第二个服务器的端口改回正确的端口并且reload生效,此时又回到第一步那样
的正常情况.
(5)第二个服务返回的是500,虽然它不是一个错误,但是如果想对它做特殊处理也是
可以的,此时在上游服务器中配置一个新的location,配置如:
location /htterr{
proxy_next_upstream http_500;
proxy_pass http://local;
};
这样就会重新选择一个上游服务器,而不把这个500返回给客户端.
此时用curl 127.0.0.1:8080/htterr测试可以发现,每次应该访问第二台服务
器的时候,都又重新自动转到第一台服务器上进行访问.因为第二台返回的是500,
代理服务器对500返回码做特殊处理--继续请求其他上游服务器.
(6)在反代服务配置中添加:
location /intercept{
proxy_intercept_errors off;
proxy_pass http://127.0.0.1:8082;
}
此时访问curl 127.0.0.1:8080/intercept直接访问8082(第二个服务器),8082返回的
状态码是500,得到“8082 Server Internal Error”;
(7)修改在反代服务配置中“location /intercept”中的配置并添加error_page的设置,如下:
server{
error_page 500 /test1.txt;
location /intercept{
proxy_intercept_errors on;
proxy_pass http://127.0.0.1:8082;
}
}
配置好之后reload,然后curl 127.0.0.1:8080/test1.txt可以看到里面的内容“test1”;
再去访问intercept,curl 127.0.0.1:8080/intercep,此时我们我们将不会再得到
“8082 Server Internal Error”这个错误了,而是返回了“test1”这个内容,因为此时
8082端口对应的这个上游服务的返回码是500,反代服务器对这个错误码做了特别的设置,
将返回给客户端的内容重定向到error_page设置的内容中去了.