nginx upstream 容錯機制

轉自:http://saiyaren.iteye.com/blog/1914865前端

1.   摘要

(1)       結論nginx

詳細描述了nginx記錄失效節點的6種狀態(time out、connect refuse、500、50二、50三、504,後四項5XX須要配置proxy_next_upstream中的狀態才能夠生效)、失效節點的觸發條件和節點的恢復條件、全部節點失效後nginx會進行恢復並進行從新監聽。算法

(2)       Nginx 負載均衡方式介紹後端

Nginx的負載均衡方式一共有4種:rr(輪詢模式)、ip_hash、fair、url_hash。centos

(3)       Ngxin負載均衡和相關反向代理配置內容緩存

Nginx負載均衡和與容錯相關的反向代理的配置。tomcat

(4)       獲取後端流程服務器

後端server的自動容錯流程圖。網絡

(5)       測試環境和測試結果session

針對幾種錯誤方式進行自動容錯測試。

2.   結論

(1)       nginx 判斷節點失效狀態

Nginx 默認判斷失敗節點狀態以connect refuse和time out狀態爲準,不以HTTP錯誤狀態進行判斷失敗,由於HTTP只要能返回狀態說明該節點還能夠正常鏈接,因此nginx判斷其仍是存活狀態;除非添加了proxy_next_upstream指令設置對40四、50二、50三、50四、500和time out等錯誤進行轉到備機處理,在next_upstream過程當中,會對fails進行累加,若是備用機處理仍是錯誤則直接返回錯誤信息(但404不進行記錄到錯誤數,若是不配置錯誤狀態也不對其進行錯誤狀態記錄),綜述,nginx記錄錯誤數量只記錄timeout 、connect refuse、50二、500、50三、504這6種狀態,timeout和connect refuse是永遠被記錄錯誤狀態,而50二、500、50三、504只有在配置proxy_next_upstream後nginx纔會記錄這4種HTTP錯誤到fails中,當fails大於等於max_fails時,則該節點失效;

(2)       nginx 處理節點失效和恢復的觸發條件

nginx能夠經過設置max_fails(最大嘗試失敗次數)和fail_timeout(失效時間,在到達最大嘗試失敗次數後,在fail_timeout的時間範圍內節點被置爲失效,除非全部節點都失效,不然該時間內,節點不進行恢復)對節點失敗的嘗試次數和失效時間進行設置,當超過最大嘗試次數或失效時間未超過配置失效時間,則nginx會對節點狀會置爲失效狀態,nginx不對該後端進行鏈接,直到超過失效時間或者全部節點都失效後,該節點從新置爲有效,從新探測;

(3)       全部節點失效後nginx將從新恢復全部節點進行探測

若是探測全部節點均失效,備機也爲失效時,那麼nginx會對全部節點恢復爲有效,從新嘗試探測有效節點,若是探測到有效節點則返回正確節點內容,若是仍是所有錯誤,那麼繼續探測下去,當沒有正確信息時,節點失效時默認返回狀態爲502,可是下次訪問節點時會繼續探測正確節點,直到找到正確的爲止。

3.   nginx負載均衡

Nginx的負載均衡方式一共有4種:rr(輪詢模式)、ip_hash、fair、url_hash;

Nginx自帶的2種負載均衡爲rr和ip_hash,fair和url_hash爲第三方的插件,nginx在不配置負載均衡的模式下,默認採用rr負載均衡模式。

l  RR負載均衡模式:

每一個請求按時間順序逐一分配到不一樣的後端服務器,若是超過了最大失敗次數後(max_fails,默認1),在失效時間內(fail_timeout,默認10秒),該節點失效權重變爲0,超過失效時間後,則恢復正常,或者所有節點都爲down後,那麼將全部節點都恢復爲有效繼續探測,通常來講rr能夠根據權重來進行均勻分配。

l  Ip_hash負載均衡模式:

每一個請求按訪問ip的hash結果分配,這樣每一個訪客固定訪問一個後端服務器,能夠解決session的問題,可是ip_hash會形成負載不均,有的服務請求接受多,有的服務請求接受少,因此不建議採用ip_hash模式,session共享問題可用後端服務的session共享代替nginx的ip_hash。

l  Fair(第三方)負載均衡模式:

按後端服務器的響應時間來分配請求,響應時間短的優先分配。

l  url_hash(第三方)負載均衡模式:

和ip_hash算法相似,是對每一個請求按url的hash結果分配,使每一個URL定向到一個同 一個後端服務器,可是也會形成分配不均的問題,這種模式後端服務器爲緩存時比較好。

4.   Nginx 負載均衡配置

Nginx的負載均衡採用的是upstream模塊

其中默認的採用的負載均衡模式是輪詢模式rr(round_robin),具體配置以下:

1)    指令:

ip_hash

語法:ip_hash 
默認值:none 
使用字段:upstream 
這個指令將基於客戶端鏈接的IP地址來分發請求。
哈希的關鍵字是客戶端的C類網絡地址,這個功能將保證這個客戶端請求老是被轉發到一臺服務器上,可是若是這臺服務器不可用,那麼請求將轉發到另外的服務器上,這將保證某個客戶端有很大機率老是鏈接到一臺服務器。
沒法將權重(weight)與ip_hash聯合使用來分發鏈接。若是有某臺服務器不可用,你必須標記其爲「down」,以下例:

upstream backend {

  ip_hash;

  server   backend1.example.com;

  server   backend2.example.com;

  server   backend3.example.com  down;

  server   backend4.example.com;

}

server

語法:server name [parameters] 
默認值:none 
使用字段:upstream 
指定後端服務器的名稱和一些參數,可使用域名,IP,端口,或者unix socket。若是指定爲域名,則首先將其解析爲IP。

l  weight = NUMBER - 設置服務器權重,默認爲1。

l  max_fails = NUMBER - 在必定時間內(這個時間在fail_timeout參數中設置)檢查這個服務器是否可用時產生的最多失敗請求數,默認爲1,將其設置爲0能夠關閉檢查,這些錯誤在proxy_next_upstream或fastcgi_next_upstream(404錯誤不會使max_fails增長)中定義。

l  fail_timeout = TIME - 在這個時間內產生了max_fails所設置大小的失敗嘗試鏈接請求後這個服務器可能不可用,一樣它指定了服務器不可用的時間(在下一次嘗試鏈接請求發起以前),默認爲10秒,fail_timeout與前端響應時間沒有直接關係,不過可使用proxy_connect_timeout和proxy_read_timeout來控制。

l  down - 標記服務器處於離線狀態,一般和ip_hash一塊兒使用。

l  backup - (0.6.7或更高)若是全部的非備份服務器都宕機或繁忙,則使用本服務器(沒法和ip_hash指令搭配使用)。

示例配置

upstream  backend  {

  server   backend1.example.com    weight=5;

  server   127.0.0.1:8080          max_fails=3  fail_timeout=30s;

  server   unix:/tmp/backend3;

}

注意:若是你只使用一臺上游服務器,nginx將設置一個內置變量爲1,即max_fails和fail_timeout參數不會被處理。
結果:若是nginx不能鏈接到上游,請求將丟失。
解決:使用多臺上游服務器。

upstream

語法:upstream name { … } 
默認值:none 
使用字段:http 
這個字段設置一羣服務器,能夠將這個字段放在proxy_pass和fastcgi_pass指令中做爲一個單獨的實體,它們能夠能夠是監聽不一樣端口的服務器,而且也能夠是同時監聽TCP和Unix socket的服務器。
服務器能夠指定不一樣的權重,默認爲1。
示例配置

upstream backend {

  server backend1.example.com weight=5;

  server 127.0.0.1:8080       max_fails=3  fail_timeout=30s;

  server unix:/tmp/backend3;

}

請求將按照輪詢的方式分發到後端服務器,但同時也會考慮權重。
在上面的例子中若是每次發生7個請求,5個請求將被髮送到backend1.example.com,其餘兩臺將分別獲得一個請求,若是有一臺服務器不可用,那麼請求將被轉發到下一臺服務器,直到全部的服務器檢查都經過。若是全部的服務器都沒法經過檢查,那麼將返回給客戶端最後一臺工做的服務器產生的結果。

2)    變量

版本0.5.18之後,能夠經過log_module中的變量來記錄日誌:

log_format timing '$remote_addr - $remote_user [$time_local]  $request '

  'upstream_response_time $upstream_response_time '

  'msec $msec request_time $request_time';

 

log_format up_head '$remote_addr - $remote_user [$time_local]  $request '

  'upstream_http_content_type $upstream_http_content_type';

l  $upstream_addr

前端服務器處理請求的服務器地址

l  $upstream_cache_status

0.8.3版本中其值可能爲:

MISS 

EXPIRED - expired。請求被傳送到後端。

UPDATING - expired。因爲proxy/fastcgi_cache_use_stale正在更新,將使用舊的應答。

STALE - expired。因爲proxy/fastcgi_cache_use_stale,後端將獲得過時的應答。

HIT

l  $upstream_status

前端服務器的響應狀態。

l  $upstream_response_time

前端服務器的應答時間,精確到毫秒,不一樣的應答以逗號和冒號分開。

l  $upstream_http_$HEADER

隨意的HTTP協議頭,如:$upstream_http_host

l  $upstream_http_host

 

3)    Proxy指令:

proxy_next_upstream

語法:proxy_next_upstream

 [error|timeout|invalid_header|http_500|http_502|http_503|http_504|http_404|off] 
默認值:proxy_next_upstream error timeout 
使用字段:http, server, location 
肯定在何種狀況下請求將轉發到下一個服務器:

error - 在鏈接到一個服務器,發送一個請求,或者讀取應答時發生錯誤。

timeout - 在鏈接到服務器,轉發請求或者讀取應答時發生超時。

invalid_header - 服務器返回空的或者錯誤的應答。

http_500 - 服務器返回500代碼。

http_502 - 服務器返回502代碼。

http_503 - 服務器返回503代碼。

http_504 - 服務器返回504代碼。

http_404 - 服務器返回404代碼。

off - 禁止轉發請求到下一臺服務器。

轉發請求只發生在沒有數據傳遞到客戶端的過程當中。

其中記錄到nginx後端錯誤數量的有500、50二、50三、50四、timeout,404不記錄錯誤。

proxy_connect_timeout

語法:proxy_connect_timeout timeout_in_seconds 
默認值:proxy_connect_timeout 60s 
使用字段:http, server, location 
指定一個鏈接到代理服務器的超時時間,單位爲秒,須要注意的是這個時間最好不要超過75秒。
這個時間並非指服務器傳回頁面的時間(這個時間由proxy_read_timeout聲明)。若是你的前端代理服務器是正常運行的,可是遇到一些情況(例如沒有足夠的線程去處理請求,請求將被放在一個鏈接池中延遲處理),那麼這個聲明無助於服務器去創建鏈接。
能夠經過指定時間單位以避免引發混亂,支持的時間單位有」s」(秒), 「ms」(毫秒), 「y」(年), 「M」(月), 「w」(周), 「d」(日), 「h」(小時),和 「m」(分鐘)。
這個值不能大於597小時。

proxy_read_timeout

語法:proxy_read_timeout time 
默認值:proxy_read_timeout 60s 
使用字段:http, server, location 
決定讀取後端服務器應答的超時時間,單位爲秒,它決定nginx將等待多久時間來取得一個請求的應答。超時時間是指完成了兩次握手後而且狀態爲established的超時時間。
相對於proxy_connect_timeout,這個時間能夠撲捉到一臺將你的鏈接放入鏈接池延遲處理而且沒有數據傳送的服務器,注意不要將此值設置過低,某些狀況下代理服務器將花很長的時間來得到頁面應答(例如如當接收一個須要不少計算的報表時),固然你能夠在不一樣的location裏面設置不一樣的值。
能夠經過指定時間單位以避免引發混亂,支持的時間單位有」s」(秒), 「ms」(毫秒), 「y」(年), 「M」(月), 「w」(周), 「d」(日), 「h」(小時),和 「m」(分鐘)。
這個值不能大於597小時。

proxy_send_timeout

語法:proxy_send_timeout seconds 
默認值:proxy_send_timeout 60s 
使用字段:http, server, location 
設置代理服務器轉發請求的超時時間,單位爲秒,一樣指完成兩次握手後的時間,若是超過這個時間代理服務器沒有數據轉發到被代理服務器,nginx將關閉鏈接。
能夠經過指定時間單位以避免引發混亂,支持的時間單位有」s」(秒), 「ms」(毫秒), 「y」(年), 「M」(月), 「w」(周), 「d」(日), 「h」(小時),和 「m」(分鐘)。
這個值不能大於597小時。

 

5.   獲取後端流程

GET_RR_PEER: 經過RR算法獲取後端流程

 

K:是判斷peer是否宕機和判斷失效狀態算法

FAIL:嘗試次數用盡有,跳轉到失敗流程,若是有備機,備機再嘗試監聽,若是監聽失敗則返回NGX_BUSY,成功則返回當前狀態

6.   測試環境

操做系統:centos5.6

Cpu:16核

內存:32g

Web 服務器:nginx

Web 應用服務器:tomcat(2臺)

7.   測試結果

l  設置tomcat1超時時間,形成超時狀態(總有一臺server爲有效狀態):

Tomcat1的connectionTimeout 設置爲-1,永遠超時,nginx設置tomcat1和tomcat2權重爲10,tomcat1的max_fails爲10,fail_timeout=120;在鏈接tomcat1的10次後,返回給nginx爲10次超時,ngxin判斷tomcat1爲失效,而後將tomcat1超時時間恢復爲1000從新啓動tomcat1,在這段時間內nginx判斷tomcat1仍是失效狀態,因此在2分鐘後,nginx繼續監聽到tomcat1正常後,那麼nginx會將tomcat1判斷爲有效,將鏈接繼續均勻分配到2個tomcat上。

l  設置tomcat1鏈接數量,形成超時狀態(總有一臺server爲有效狀態):

Tomcat1的線程數量設置爲1,nginx設置tomcat1和tomcat2權重爲10,tomcat1的max_fails爲10,fail_timeout=120;在鏈接tomcat1超過線程接受數量後,tomcat1會返回超時狀態,在返回給nginx10次超時狀態後,ngxin判斷tomcat1爲失效,而後將tomcat線程數量恢復爲700,從新啓動tomcat1,在這段時間內nginx判斷tomcat1仍是失效狀態,超過2分鐘失效後,nginx繼續監聽到tomcat1正常後,那麼nginx會將tomcat1判斷爲有效,將鏈接繼續均勻分配到2個tomcat上。

l  設置tomcat1關閉,形成拒絕狀態(總有一臺server爲有效狀態):

Tomcat1爲關閉,nginx設置tomcat1和tomcat2權重爲10,tomcat1的max_fails爲10,fail_timeout=120;在鏈接tomcat1的10次後,nginx收到tomcat1返回connect refuse狀態,ngxin判斷tomcat1爲失效,而後從新啓動tomcat1,在這段時間內nginx判斷tomcat1仍是失效狀態,超過2分鐘失效後,nginx繼續監聽到tomcat1正常後,那麼nginx會將tomcat1判斷爲有效,將鏈接繼續均勻分配到2個tomcat上。

l  設置tomcat1在nginx1標記失效,tomcat1恢復正常,在nginx失效範圍內,將所有服務變爲失效,而後重啓:

Tomcat1爲關閉,nginx設置tomcat1和tomcat2權重爲10,tomcat1的max_fails爲10,fail_timeout=120;在鏈接tomcat1的10次後,nginx收到tomcat1返回connect refuse狀態,ngxin判斷tomcat1爲失效,而後從新啓動tomcat1,在這段時間內nginx判斷tomcat1仍是失效狀態,而後將tomcat2關閉,而後重啓tomcat2,因爲全部服務均失效,因此nginx 將全部服務從新置爲有效進行監聽,而後將2鏈接均勻分佈到了tomcat1和tomcat2上。

l  http錯誤狀態,nginx是否記錄失效:

nginx設置tomcat1和tomcat2權重爲10,tomcat1的max_fails爲10,fail_timeout=120;配置proxy_next_upstream 500、40四、50二、50三、50四、timeout後,當HTTP狀態爲500、50二、50三、504(timeout和refuse默認是記錄失效的)時,nginx會判斷該次請求爲失敗記錄失敗狀態,其餘全部HTTP均不記錄失敗。

相關文章
相關標籤/搜索