proxy_next_upstream
当上游返回失败的时候,我们是有些处理方法的,这个处理方法就是通过proxy_next_upstream这么一个指令来控制的。当然了该指令能够生效的前提是我们没有向客户端发送一个字节,即没有向客户端发送任何的内容,只要向客户端发送了一个字节了,说明上游服务已经生效了,那么我们就不能再选择一个新的上游服务了。所以它是在接收到请求并且在转发一个字节之前,nginx判定为错误,那么这个功能才能够生效。
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
error:nginx与上游建立连接,读取响应发送请求等等这些过程当中出现错误,那么error都可以满足这样一个场景,这个错误指的是网络错误,比如TCP层等。
timeout:超时,有connect timeout,read timeout,write timeout。那么配置了timeout可以命中这些场景,当命中这些场景可以重选上游服务。
错误的连接由proxy_next_upstream, fastcgi_next_upstream等指令决定,且默认情况下后端某台服务器出现故障了,nginx会自动将请求再次转发给其他正常的服务器(因为默认proxy_next_upstream error timeout)。所以即使我们没有配这个参数,nginx也可以帮我们处理error和timeout的相应,但是没法处理404等报错,就是如果资源找不到还是会报错的。(如果后端服务器上有多台,只要有一台上没有用户要访问的资源就会报404错误)
proxy_next_upstream off|error|404
proxy_next_upstream off
192.168.179.99代理服务器配置:
server {
listen 80;
server_name www.test.com;
location /{
proxy_pass http://web;
proxy_connect_timeout 1s; #为了让其更好的显示结果配置为1s
proxy_next_upstream off;
}
}
upstream web{ #使用round-robin轮询算法
server 192.168.179.100 ;
server 192.168.179.101 ;
}
#上游的两台服务器均可以正常访问
[root@www ~]# curl 192.168.179.100
proxy this is 192.168.179.100 page
[root@localhost ~]# curl 192.168.179.101
proxy this is 192.168.179.101 page
#可以看到使用了轮询算法
[root@www conf]# while true;do curl 192.168.179.99;sleep 1;done
proxy this is 192.168.179.100 page
proxy this is 192.168.179.101 page
proxy this is 192.168.179.100 page
proxy this is 192.168.179.101 page
#将192.168.179.100上游服务器关闭,再去访问代理服务器
[root@www ~]# pkill nginx
[root@www ~]# curl 192.168.179.100
curl: (7) Failed connect to 192.168.179.100:80; Connection refused
#可以看到使用轮询,返回给客户端502报错
[root@www conf]# while true;do curl 192.168.179.99;sleep 1;done
<html>
<head><title>502 Bad Gateway</title></head>
<body>
<center><h1>502 Bad Gateway</h1></center>
<hr><center>nginx/1.16.1</center>
</body>
</html>
proxy this is 192.168.179.101 page
proxy this is 192.168.179.101 page
proxy this is 192.168.179.101 page
proxy_next_upstream error
#和上面一样只不过将off去掉,开启error
location /{
proxy_pass http://web;
proxy_connect_timeout 1s;
proxy_next_upstream error;
}
#再去访问可以看到没有显示502的报错,这是因为proxy_next_upstream生效了,该功能可以屏蔽返回客户端的错误
[root@www conf]# while true;do curl 192.168.179.99;sleep 1;done
proxy this is 192.168.179.101 page
proxy this is 192.168.179.101 page
proxy this is 192.168.179.101 page
proxy this is 192.168.179.101 page
proxy this is 192.168.179.101 page
#这个时候将宕机的192.168.179.100重启之后信息又会恢复正常
[root@www conf]# while true;do curl 192.168.179.99;sleep 1;done
proxy this is 192.168.179.100 page
proxy this is 192.168.179.101 page
proxy this is 192.168.179.100 page
proxy this is 192.168.179.101 page
proxy_next_upstream 404
nginx没法处理404等报错,就是如果资源找不到还是会报错的。(如果后端服务器上有多台,只要有一台上没有用户要访问的资源就会报404错误,即后端服务器资源要保持一致)192.168.179.100上模拟客户端要访问的资源不存在,但是这个资源在192.168.179.101上存在。
[root@www ~]# mv /usr/local/nginx/html/index.html /usr/local/nginx/html/index.html.bak
server {
listen 80;
server_name www.test.com;
charset utf-8;
location /{
proxy_pass http://web;
proxy_next_upstream error;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
[root@localhost nginx-1.16.1]# while true;do curl 192.168.179.99/index.html;sleep 1;done --可以看到返回404报错了
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8" />
<title>this is 404 page</title>
</head>
<body>
<!--<script type="text/javascript"
src="http://www.qq.com/404/search_children.js"></script>-->
<script type="text/javascript"
src="//qzonestyle.gtimg.cn/qzone/hybrid/app/404/search_children.js"
charset="utf-8"></script>
</body>
</html>
proxy this is 192.168.179.101 page
可以看到上面是两台服务器上的资源不一致导致的返回404,如果需要临时解决可以在proxy_next_upstream后面加上http_404,通过这个指令,可以处理当后端服务返回404等报错时,直接将请求转发给其他服务器,而不是把报错信息返回客户端。
server {
listen 80;
server_name www.test.com;
charset utf-8;
location /{
proxy_pass http://web;
proxy_next_upstream error http_404;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
[root@localhost nginx-1.16.1]# while true;do curl 192.168.179.99;sleep 1;done --再去访问可以发现404错误没有了
proxy this is 192.168.179.101 page
proxy this is 192.168.179.101 page
proxy this is 192.168.179.101 page
proxy this is 192.168.179.101 page