【充电】《Nginx核心知识100讲》proxy模块:上游出现失
极客专栏《Nginx核心知识100讲》95小节,笔记
注意:这个是看专栏视频,敲的哈。这个专栏让我收货蛮大的。
95 | 上游出现失败时的容错方案
我们讨论了nginx作为反向代理时,从客户端接收http body,到完整的接收上游的响应并转发响应的流程。其中在nginx与上游服务建立连接时。提到过proxy_next_upstream指令。这个指令可以在第一台的错误的响应返回给客户端这样的功能。这节课讨论这个功能是怎么使用的。
上游失败的处理方法
image.png能够生效的前提是没有向客户端发送一个字节。只要向客户端已经发送了一个字节了。说明上游的服务已经生效了,就不能选用一个新的上游服务了。它一定是在接收到并开始转发一个字节之前nginx判定为错误,这个功能才能生效。proxy_next_upstream后面可以跟很多不同的参数(error、timeout那些)。
配置
error:nginx与上游建立连接读取响应,发送请求等等这些过程中,只要出现错误等等。error都可以满足这样的场景。这种错误主要是网络错误。比如TCP层、IP层的错误。
timeout:超时有connection timeout 、read timeout、 write timeout,这个timeout可以命中这些场景。当出现这种场景的时候将执行重选另一个上游服务。
invalid_header则是我们收到的上游服务http header,它是不合法的。
http_:http_可以跟一个明确的响应code。上游返回一个403或500,其实它既不是网络错误,也不是超时,也不是invalid_header。但是我们就是可以针对这样的错误从新选择一个新的upstream上游去处理。
non_idempotent:根据RFC 7231文档中规定了post、lock等method的请求。在上游服务不能使用next_upstream上游服务的,去重选一个新的服务时候,当我们配置了这个non_idempotent就可以启用proxy_next_upstream功能。
off:关闭 proxy_next_upstream功能。
image.png演示
第一个演示,error 的演示
反向代理nginx 配置
image.pngproxy_next_upstream设置为off。为了很快的显示出错误的结果,connect_timeout 设置了1s。
上游的配置
image.png能从8011和8013的返回的错误看出区别。
image.png下面把8011改成8014
image.png因为8013端口不存在了。所以报错了。
image.png把proxy_next_upstream改成error。
image.png image.png出现上图的原因是。虽然使用的是round-robin算法。但是每次都能获取返回值。但其实8013端口不在监听了。原因是proxy_next_upstream生效了,发现8013不存在了,就会重新改用新的upstream来为用户服务,这个功能可以让nginx把错误屏蔽掉。这是对于分布式集群下非常好用的功能。客户端每一次api或一次请求都没有拿到错误。
第二个演示,对返回状态码做处理
8014再改回到8013端口。
image.pnghttp_500的意思是,当我收到500的错误码,我仍然把它当成错误从新选择一个新的upstream,而不把这个500返回给客户端。
image.png看结果,因为把500做处理,所以请求中无法看到8013的返回。nginx重新选择8011作为返回结果。
拦截上游失败响应
image.pngproxy_intercept_errors 默认off。这个时候上游返回怎样的响应。客户端就会原封不动的拿到这个响应。比如上游返回来一个404,我们的error_page 配置的404是不会生效的。只有把proxy_intercept_errors 设置为on的时候error_page 就会生效了。
演示
nginx配置,proxy_intercept_errors 为off
image.png8013 返回500的错误
image.pngproxy_intercept_errors 为on时,配置了error_page,发现500错误码的时候返回test1.txt。
image.png image.png这次看到请求的返回值变成了test1
(也就是test1文件的内容)。
留言问题
1.nginx 默认的proxy_next_upstream 应该是配置了error和timeout,max_fails=1 fail_timeout=10s。这样如果后端的设备不是全部故障的话,应该不会出现异常的页面吧。
但是我这里使用了缓存后,就不会自动切换了,不知为何,配置如下。
proxy_cache_path /home/yum_cache/ levels=1:2 keys_zone=cache1:1024m inactive=1d max_size=30g;
upstream "yumproxy" {
server 192.168.1.10:80;
server 192.168.2.10:80 backup;
}
location ~ .(php|xml)host;
proxy_set_header X-Forwarded-For hostis_args$args;
access_log logs/cache.log main;
proxy_cache_valid 200 304 301 302 1m;
在此指定时间过期后,会主动去源服务器更新数据信息
proxy_cache_valid any 0s;
}
location / {
proxy_pass http://yumproxy;
}
根据这个配置,如果主节点异常了,理论上backup的节点应该会被直接访问到,但是当我把主节点停掉的时候,再访问这个缓存节点的时候,就会出现502的错误。
作者回复
你用的是哪个版本的Nginx?我根据你的配置,在我的服务器上修改后,发现主节点异常后仍然正常跳到backup节点,没有收到502。
我用的是最新的Nginx版本。
2.测试了一把,需要在upstream 中的每一条后端记录上添加这个指标 max_fails=1 fail_timeout=60s。然后可以实现异常后自动将其摘除60s。
可以实现自动检测的 貌似可以用淘宝的模块nginx_upstream_check_module-master 实现
作者回复
淘宝的模块可以定期通过心跳检查上游,与本节课介绍方式不太一样:-)