現在對外服務的網站,很少只使用一個服務節點,而是部署多台服務器,上層通過一定機制保證容錯和負載均衡。
nginx就是常用的一種HTTP和反向代理服務器,支持容錯和負載均衡。
nginx的重試機制就是容錯的一種。
在nginx的配置文件中,proxy_next_upstream項定義了什么情況下進行重試,官網文檔中給出的說明如下:
---------------------
Syntax: proxy_next_upstream error | timeout | invalid_header | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | off ...;
Default: proxy_next_upstream error timeout;
Context: http, server, location
---------------------
上面的配置表示,如果后端服務器如下情況,將會把請求轉發到下一台后端服務器上。
- error - 在連接到一個服務器,發送一個請求,或者讀取應答時發生錯誤。
- timeout - 在連接到服務器,轉發請求或者讀取應答時發生超時。
- invalid_header - 服務器返回空的或者錯誤的應答。
- http_502 - 服務器返回502代碼。
- http_504 - 服務器返回504代碼。
默認情況下,當請求服務器發生錯誤或超時時,會嘗試到下一台服務器。
還有一個參數影響了重試的次數:proxy_next_upstream_tries,官方文檔中給出的說明如下:
Syntax: proxy_next_upstream_tries number;
Default: proxy_next_upstream_tries 0;
Context: http, server, location
This directive appeared in version 1.7.5.
該配置決定了最多重試多少次,0表示不限制。
不了解這個機制,在日常開發web服務的時候,就可能會踩坑。
比如有這么一個場景:一個用於導入數據的web頁面,上傳一個excel,通過讀取、處理excel,向數據庫中插入數據,處理時間較長(如1分鍾),且為同步操作(即處理完成后才返回結果)。暫且不論這種方式的好壞,若nginx配置的響應等待時間(proxy_read_timeout)為30秒,就會觸發超時重試,將請求又打到另一台。如果處理中沒有考慮到重復數據的場景,就會發生數據多次重復插入!(當然,這種場景,內網可以通過機器名訪問該服務器進行操作,就可以繞過nginx了,不過外網就沒辦法了。)
同理,在處理POST請求的時候也需要注意類似的問題。網上有一篇討論如何阻止POST請求的超時重試,感興趣的可以看看點擊打開鏈接
nginx常用的超時配置說明
client_header_timeout
語法 client_header_timeout time
默認值 60s
上下文 http server
說明 指定等待client發送一個請求頭的超時時間(例如:GET / HTTP/1.1).僅當在一次read中,沒有收到請求頭,才會算成超時。如果在超時時間內,client沒發送任何東西,nginx返回HTTP狀態碼408(“Request timed out”)
client_body_timeout
語法 client_body_timeout time
默認值 60s
上下文 http server location
說明 該指令設置請求體(request body)的讀超時時間。僅當在一次readstep中,沒有得到請求體,就會設為超時。超時后,nginx返回HTTP狀態碼408(“Request timed out”)
keepalive_timeout
語法 keepalive_timeout timeout [ header_timeout ]
默認值 75s
上下文 http server location
說明 第一個參數指定了與client的keep-alive連接超時時間。服務器將會在這個時間后關閉連接。可選的第二個參數指定了在響應頭Keep-Alive: timeout=time中的time值。這個頭能夠讓一些瀏覽器主動關閉連接,這樣服務器就不必要去關閉連接了。沒有這個參數,nginx不會發送Keep-Alive響應頭(盡管並不是由這個頭來決定連接是否“keep-alive”)
兩個參數的值可並不相同
注意不同瀏覽器怎么處理“keep-alive”頭
MSIE和Opera忽略掉"Keep-Alive: timeout=<N>" header.
MSIE保持連接大約60-65秒,然后發送TCP RST
Opera永久保持長連接
Mozilla keeps the connection alive for N plus about 1-10 seconds.
Konqueror保持長連接N秒
lingering_timeout
語法 lingering_timeout time
默認值 5s
上下文 http server location
說明 lingering_close生效后,在關閉連接前,會檢測是否有用戶發送的數據到達服務器,如果超過lingering_timeout時間后還沒有數據可讀,就直接關閉連接;否則,必須在讀取完連接緩沖區上的數據並丟棄掉后才會關閉連接。
resolver_timeout
語法 resolver_timeout time
默認值 30s
上下文 http server location
說明 該指令設置DNS解析超時時間
proxy_connect_timeout
語法 proxy_connect_timeout time
默認值 60s
上下文 http server location
說明 該指令設置與upstream server的連接超時時間,有必要記住,這個超時不能超過75秒。
這個不是等待后端返回頁面的時間,那是由proxy_read_timeout聲明的。如果你的upstream服務器起來了,但是hanging住了(例如,沒有足夠的線程處理請求,所以把你的請求放到請求池里稍后處理),那么這個聲明是沒有用的,由於與upstream服務器的連接已經建立了。
proxy_read_timeout
語法 proxy_read_timeout time
默認值 60s
上下文 http server location
說明 該指令設置與代理服務器的讀超時時間。它決定了nginx會等待多長時間來獲得請求的響應。這個時間不是獲得整個response的時間,而是兩次reading操作的時間。
proxy_send_timeout
語法 proxy_send_timeout time
默認值 60s
上下文 http server location
說明 這個指定設置了發送請求給upstream服務器的超時時間。超時設置不是為了整個發送期間,而是在兩次write操作期間。如果超時后,upstream沒有收到新的數據,nginx會關閉連接
proxy_upstream_fail_timeout(fail_timeout)
語法 server address [fail_timeout=30s]
默認值 10s
上下文 upstream
說明 Upstream模塊下 server指令的參數,設置了某一個upstream后端失敗了指定次數(max_fails)后,該后端不可操作的時間,默認為10秒
websocket 1分鍾會自動斷開問題
location 中的proxy_read_timeout 默認60s斷開,可以把他設置大一點
原文:https://blog.csdn.net/u013378306/article/details/71190862