Nginx故障转移带来的雪崩问题

一、nginx故障转移

我们都知道nginx可以用作负载均衡可以通过轮训、weight、ip_hash、url_hash、fair的方式很好的分散请求的压力。基于nginx阿里也有自己的tengin。
同时Nginx可以对故障转移进行配置,相关的配置项如下所示:

server  
{  
     listen       80;  
     server_name   www.yourdomain.com 192.168.203.42;  
     index index.html index.htm;  
     root   /data/htdocs/www;    
 
    location /  
    {  
     #故障转移的条件:如果后端的服务器返回502504、执行超时等错误,自动将请求转发到upstream负载均衡池中的另一台服务器,实现故障转移。  
     proxy_next_upstream http_502 http_504 error timeout invalid_header;  
     
     proxy_send_timeout 10s;    # 代理发送超时时间
     proxy_read_timeout 10s;    # 代理接收超时时间
     proxy_next_upstream_tries 3;      # 重试次数

     proxy_cache cache_one;  
       
     #对不同的HTTP状态码设置不同的缓存时间  
     proxy_cache_valid   200 304 12h;  
       
     #以域名、URI、参数组合成Web缓存的Key值,Nginx根据Key值哈希,存储缓存内容到二级缓存目录内  
     proxy_cache_key $host$uri$is_args$args;  
     proxy_set_header Host   $host;  
     proxy_set_header X-Forwarded-For   $remote_addr;  
     proxy_pass http://backend_server;  
     expires       1d;  
    }  
} 

在这里插入图片描述
如配置webserver1、webserver2、webserver3 三台集群,当有请求过来时会根据配置的负载均衡策略进行请求转发。如请求A被转发到webserver1中,但因为webserver服务器压力过大,产生了proxy_next_upstream中配置的现象,如超时未返回数据等现象,便会出发nginx的故障转移机制,将请求转发到其余服务器上进行处理。

好处: 保证了集群的高可用
坏处: 频繁的进行请求转发会给集群带来压力,甚至造成雪崩。

二、事件

2.1 问题描述:

有一个发送短信的http服务,客户端调用之后,只有一次请求,但是发了三次短信。

分析:

 1、客户端仅发起了一次请求,

 2、服务端收到了三次请求

 3、三次请求分别落在了三台后端机器上。每台后端机器仅收到一次请求

2.2 基本的架构:

在这里插入图片描述

2.3 分析及解决:

 分析代码,代码中没有重试机制,并且通过请求分布来看,并不是一台机器处理了三次,而是每台机器处理了一次。所以分析,可能是由于nginx转发导致。 

 查看接口的响应时间,发现每个接口的响应时间为18s左右(PS:由于是调用外部接口,此调用时间属于正常的时间。。。)。

 猜测是由于后端服务器未能及时返回数据,导致了nginx的超时重试机器,将请求分发到了另外一台机器上。

 查看nginx的配置文件,发现如下配置:
proxy_next_upstream http_502 http_504 error timeout invalid_header;

上面的配置表示,如果后端服务器如下情况,将会把请求转发到下一台后端服务器上。

error - 在连接到一个服务器,发送一个请求,或者读取应答时发生错误。
timeout - 在连接到服务器,转发请求或者读取应答时发生超时。
invalid_header - 服务器返回空的或者错误的应答。
http_502 - 服务器返回502代码。
http_504 - 服务器返回504代码。

继续查看超时时间

proxy_read_timeout 15;

超时时间为15s,所以后端服务器响应慢,nginx没有在15s内收到返回的数据,所以将请求切换到下一台后端机器了,所以,同样的情况下, 请求第二台后端机器时,也没有在规定的时间内得到响应,所以又切换到第三台机器了,最终导致短信发送了三次。

几个参数说明:


proxy_send_timeout     后端服务器数据回传时间(代理发送超时时间)

proxy_read_timeout      连接成功后,后端服务器响应时间(代理接收超时时间)

proxy_connect_timeout    nginx连接后端的超时时间,一般不超过75s

如何解决呢?

第一种办法:因为后端机器无法再进行优化减少响应时间,所以可以更改nginx的超时时间,将原本的15s更改为40s,这样可以保证结果正常返回。

第二种办法 :关闭自动切换到下台机器的功能,即将proxy_next_upstream配置为off。但是这样虽然能解决问题,但是会导致nginx的容错能力下降。

第三种,最后的才是最香的:
nginx的熔断机制:

当某台被代理服务器处理请求,出现一定次数的错误的情况下,nginx在一定时间内不再将请求分配给这台服务器进行处理。 过了熔断时间后,nginx会再次尝试分配一次请求给该服务器处理,如果还是失败,那么继续熔断。

upstream指令块中server定义的熔断参数配置:

max_fails = number; # 熔断机制的错误次数 阈值(默认1)
fail_timeout = time #熔断时间(nginx标记服务器不可用的持续时间,默认10s)

示例: server 192.168.1.100 max_fails=3 fail_timeout= 10s;

在这里插入图片描述

以上现象还可能出现在以下的场景:

1、上传excel,然后服务端处理excel内容,插入到db里面的时候,可能存在多次转发导致数据重复。

2、post请求处理时间过长,可能出现重复提交的问题。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章