nginx超時重試機制及潛在的坑


本文地址:http://www.dutycode.com/nginx_chongshi_chongfuqingqiu.html
除非注明,文章均為 www.dutycode.com 原創,歡迎轉載!轉載請注明本文地址,謝謝。

問題描述:
有一個發送短信的http服務,客戶端調用之后,只有一次請求,但是發了三次短信。

分析看:
     1、客戶端僅發起了一次請求,
     2、服務端收到了三次請求
     3、三次請求分別落在了三台后端機器上。每台后端機器僅收到一次請求

基本的架構如下:
93914042-18CE-4EEB-BB84-C38756515AC1.png

分析及解決:
     分析代碼,代碼中沒有重試機制,並且通過請求分布來看,並不是一台機器處理了三次,而是每台機器處理了一次。所以分析,可能是由於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


如何解決呢?
     1、第一種辦法:因為后端機器無法再進行優化減少響應時間,所以可以更改nginx的超時時間,將原本的15s更改為40s,這樣可以保證結果正常返回。
      2、第二種辦法 :關閉自動切換到下台機器的功能,即將proxy_next_upstream配置為off。但是這樣雖然能解決問題,但是會導致nginx的容錯能力下降。
     3、第三種辦法:從業務角度出發,本質上我們是需要只發一次短信的。 所以可以采用分布式鎖的方式解決。


以上現象還可能出現在以下的場景:
1、上傳excel,然后服務端處理excel內容,插入到db里面的時候,可能存在多次轉發導致數據重復。
2、post請求處理時間過長,可能出現重復提交的問題。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM