NGINX 負載均衡
NGINX 負載均衡
利用 NGINX 在多個服務例項中做負載均衡是 NGINX 最常用的場景之一。在將我們現在做的產品放到公司的 AWS 上的時候,我接觸到了這些,並且修改了 CI team 的部分 NGINX 配置,讓它能夠正確地完成反向代理的工作。
配置
在做負載均衡前,我們首先需要定義一個 Server 組用來表示所有存在的後臺服務:
http { upstream backend { server backend1.example.com weight=5; server backend2.example.com; server 192.0.0.1 backup; } }
然後,我們需要把流量重定向到上一步定義的 backend 上去, 我們可以通過指定 proxy_pass 的值來完成這一操作:
upstream backend { server backend1.example.com; server backend2.example.com; server 192.0.0.1 backup; } server { location / { proxy_pass http://backend; } } }
這裡我們將所有的流量重定向到ofollow,noindex">http://backend , 這將這個 NGINX 例項上的所有流量重定向到之前定義的 backend 上去。
負載均衡演算法
當沒有指定任何資訊時, NGINX 預設使用了 Round Robin(輪詢)演算法來重定向流量。其實 NGINX 提供了多種演算法來做負載均衡,下面我們來介紹一下:
Round Robin (輪詢)
在沒有指定 weight(權重) 的情況下,Round Robin 會將所有請求均勻地分發給所有後臺服務例項:
upstream backend { server backend1.example.com; server backend2.example.com; }
這裡我們沒有指定權重,所以兩個後臺服務會收到等量的請求。但是,當指定了權重之後,NGINX 就會將權重考慮在內:
upstream backend { server backend1.example.com weight=5; server backend2.example.com; }
在 NGINX 中,weight 預設被設定為 1。這裡我們用一開始的配置舉例, backend1.example.com 的權重被設定為 5,另一個的權重沒設定,所以是預設值 1。我們也沒有設定輪詢演算法,所以這時候 NGINX 會以 5:1 的比例轉發請求,即 6 個請求中, 5 個被放到了 backend1.example.com 上, 有一個被髮到了 backend2.example.com 上。
Least Connections(最少連線演算法)
在這個模式下,一個請求會被 NGINX 轉發到當前活躍請求數量最少的服務例項上:
upstream backend { least_conn; server backend1.example.com; server backend2.example.com; }
我們用 least_conn 來指定最少連線優先演算法, NGINX 會優先轉發請求到現有連線數少的那一個服務例項上。
IP Hash (IP 雜湊)
在 IP Hash 模式下,NGINX 會根據傳送請求的 IP 地址的 hash 值來決定將這個請求轉發給哪個後端服務例項。被 hash 的 IP 地址要麼是 IPv4 地址的前三個 16 進位制數或者是整個 IPv6 地址。使用這個模式的負載均衡模式可以保證來自同一個 IP 的請求被轉發到同一個服務例項上。當然,這種方法在某一個後端例項發生故障時候會導致一些節點的訪問出現問題。
upstream backend { ip_hash; server backend1.example.com; server backend2.example.com; }
如果某一臺伺服器出現故障或者無法進行服務,我們可以給它標記上 down,這樣之前被轉發到這臺伺服器上的請求就會重新進行 hash 計算並轉發到新的服務例項上:
upstream backend { server backend1.example.com; server backend2.example.com; server backend3.example.com down; }
Generic Hash(通用雜湊)
這個模式允許管理員自定義 hash 函式的輸入,比如:
upstream backend { hash $reqeust_uri consistent; server backend1.example.com; server backend2.example.com; }
在這個例子中,我們以請求中所帶的 url 為 hash 的輸入。
注意到這裡在 hash 那一行的最後加入了 consistent 這個關鍵詞。這個關鍵詞會使用一種新的 hash 演算法ketama , 該演算法會讓管理員新增或刪除某個服務例項的時候,只有一小部分的請求會被轉發到與之前不同的服務例項上去,其他請求仍然會被轉發到原有的服務例項上去。
Random (隨機演算法)
顧名思義,每個請求都被隨機發送到某個服務例項上去:
upstream backend { random; server backend1.example.com; server backend2.example.com; server backend3.example.com; server backend4.example.com; }
Random 模式還提供了一個引數 two,當這個引數被指定時,NGINX 會先隨機地選擇兩個伺服器(考慮 weight),然後用以下幾種方法選擇其中的一個伺服器:
1. `least_conn`: 最少連線數 2. `least_time=header(NGINX PLUS only)`: 接收到 response header 的最短平均時間 3. `least_time=last_byte(NGINX PLUS only)`: 接收到完整請求的最短平均時間
我們可以參考下面的一個例子:
upstream backend { random two least_time=last_byte; server backend1.example.com; server backend2.example.com; server backend3.example.com; server backend4.example.com; }
當環境中有多個負載均衡伺服器在向後端服務轉發請求時,我們可以考慮使用 Random 模式,在只有單個負載均衡伺服器時,一般不建議使用 Random 模式。
Least Time (NGINX PLUS only)
這是一個 NGINX PLUS (NGINX 的付費版) 才有的模式,可以將請求優先轉發給平均響應時間較短的服務例項,它也有三個模式:
1. `header`: 從伺服器接收到第一個位元組的時間 2. `last_byte`: 從伺服器接收到完整的 response 的時間 3. `last_byte inflight`: 從伺服器接收到完整地 response 的時間(考慮不完整的請求)
例子如下:
upstream backend { least_time header; server backend1.example.com; serverbackend2.example.com; }
總結
NGINX 提供了多種負載均衡模式,在實際使用中,需要根據實際業務需求去做嘗試,分析日誌來找到最適合當前場景的複雜均衡模式。