1. 程式人生 > >NGINX 負載均衡原理及應用

NGINX 負載均衡原理及應用

Nginx負載均衡與可用性檢查

在業界,一直流傳這樣一句話:Nginx抗併發能力強!為什麼Nginx抗併發能力強?原因是使用了非阻塞、非同步傳輸
阻塞:如apache代理tomcat時,apache開啟10個程序,同時處理著10個請求,在tomcat沒有返回給apache結果時,apache是不會處理使用者發出的第11個請求
非阻塞:如nginx代理tomcat時,nginx開啟1000個併發,同時處理著1000個請求,在tomcat沒有返回給nginx結果時,nginx會依然處理後面使用者發給的請求
同步傳輸:比如squid代理tomcat時,瀏覽器發起請求,然後請求會squid立刻被轉到後端伺服器,於是在瀏覽器和後端伺服器之間就建立了一個連線。在請求發起到請求完成,這條連線都是一直存在的。
非同步傳輸

:比如nginx代理tomcat時,瀏覽器發起請求,請求不會立刻轉到後端伺服器,而是將請求資料(header)先儲存到nginx上,然後nginx再把這個請求發到後端伺服器, 後端伺服器處理完之後把資料返回到nginx上,nginx將資料流發到瀏覽器。
1.png

2012-7-26 21:19:08 上傳

     如上圖所示假設使用者執行一個上傳檔案操作,由於使用者網速較慢,因此需要花半個小時才能把檔案傳到伺服器。squid的同步代理在使用者開始上傳後就和 後端tomcat建立了連線,半小時後檔案上傳結束,所以,後端tomcat伺服器連線保持了半個小時;而nginx非同步代理就是先將資料儲存在 nginx上,因此僅僅是nginx和使用者 保持了半小時連線,後端伺服器在這半小時內沒有為這個請求開啟連線,半小時後使用者上傳結束,nginx才將上傳內容發到後端tomcat,nginx和後 臺之間的頻寬 是很充裕的,所以只花了一秒鐘就將請求傳送到了後臺,由此可見,後端伺服器連線保持了一秒。

一、負載均衡
1、負載均衡模組(upstream)

Upstream模組是Nginx 負載均衡的主要模組,它提供了簡單的辦法來實現在輪詢和客戶端IP之間的後端伺服器負載均衡,並可以對伺服器進行健康檢查。upstream並不處理請 求,而是通過請求後端伺服器得到使用者的請求內容。在轉發給後端時,預設是輪詢,也可以是ip_hash。

Nginx常見負載均衡方式
輪詢(預設):按照每個請求時間的順序的分配到後端伺服器
ip_hash:每個請求按訪問ip的hash結果分配
weight:按照權重輪詢,權重值越高,輪詢機率越大
fair(三方):按後端伺服器的響應時間來分配請求,響應時間短的優先分配
url_hash(三方):根據url的hash結果進行分配

下面為一組伺服器負載均衡的集合:
upstream info_pool {
                     ip_hash;
                     server 110.4.111.28:8081 max_fails=2 fail_timeout=5s;
                     server 110.4.111.29:8081 max_fails=2 fail_timeout=5s;
                     server 110.4.111.30:8081 max_fails=2 fail_timeout=5s;
                     }

Upstream相關指令解釋:
max_fails:定義定義可以發生錯誤的最大次數
fail_timeout:nginx在fail_timeout設定的時間內與後端伺服器通訊失敗的次數超過max_fails設定的次數,則認為這個伺服器不在起作用;在接下來的 fail_timeout時間內,nginx不再將請求分發給失效的server
down:把後端標記為離線,僅限於ip_hash
backup:標記後端為備份伺服器,若後端伺服器全部無效時才啟用

upstream中使用ip_hash模式時,為什麼weight選項會被忽略?
因為ip_hash模式使用的負載均衡演算法是根據請求ip進行hash,而weight模式使用的wrr演算法,所以不可同時使用

2、代理模組(proxy)
    Proxy為Nginx的代理模組,允許負責將使用者的HTTP請求轉發到後端伺服器,同時也可以結合upstream模組,達到負載均衡的目的
注:proxy相關功能、指令很多,在此只講與upstream相關的指令和功能

proxy模組常用指令解釋:
proxy_pass:指定轉發到後端伺服器的請求,在location中指定,常用URI型別如下
TCP套接字:proxy_pass http://127.0.0.1:8080;
Unix套接字:proxy_pass http://unix:/tmp/nginx.sock;
Upstream區段:proxy_pass http://nginx_pool;
域名:proxy_pass http://www.a.com;

proxy_pass使用域名命名時,為什麼不能和server_name相同 ?
nginx解析.jpg

如上圖所以,其資料訪問流如下:
①        、使用者訪問www.a.com,server_name指令監聽並接受www.a.com請求內容
②        、server_name將www.a.com的請求轉交給proxy_pass指令處理
③        、proxy_pass接到請求後根據相應URI進行處理(此處URI為www.a.com),因為我們此處URI為域名,所以proxy_pass會請求DNS進行解析
④        、proxy_pass收到DNS解析結果(www.a.com),去請求server_name
由此可見如果proxy_pass的URI命名若和server_name命名相同,則形成一個請求環路。所以在配置proxy_pass的URI時,應避免和本server內的server_name重名

二、健康檢查
   Nginx的健康檢查主要體現在對後端服務提供健康檢查,且功能被整合在upstream模組中,共有兩個指令
max_fails:定義定義可以發生錯誤的最大次數
fail_timeout:nginx在fail_timeout設定的時間內與後端伺服器通訊失敗的次數超過max_fails設定的次數,則認為這個伺服器不在起作用;在接下來的 fail_timeout時間內,nginx不再將請求分發給失效的server。
健康檢查機制:
   Nginx在檢測到後端伺服器故障後,nginx依然會把請求轉向該伺服器,當nginx發現timeout或者refused後,會把改請求會分發到 upstream的其它節點,直到獲得正常資料後,nginx才會把資料返回給使用者,這也便體現了nginx的非同步傳輸,而lvs/haproxy /apache責無法做到這些(在lvs/haproxy/apache裡,每個請求都只有一次機會,假如使用者發起一個請求,結果該請求分到的後端伺服器 剛好掛掉了,那麼這個請求就失敗了)