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請求處理時間過長,可能出現重複提交的問題。

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