文章目錄
- 一、Nginx負載均衡基本概述
- 1.1 什么是負載均衡
- 1.2 為什么需要負載均衡
- 1.3 負載均衡與代理區別
- 二、Nginx負載均衡應用場景
- 2.1 四層負載均衡
- 2.2 七層負載均衡
- 2.3 四層負載均衡與七層負載均衡區別
- 三、Nginx負載均衡配置
- 3.1 負載均衡場景環境準備
- 3.2 后端Web節點配置實體
- 3.3.前端接入Nginx負載均衡
- 3.4.瀏覽器訪問測驗負載均衡效果
- 3.5 wordpress專案負載均衡配置
- 四、Nginx負載均衡調度演算法
- 4.1 輪詢調度演算法
- 4.2 加權輪詢調度演算法
- 4.3 ip_hash調度演算法
- 4.4 一致性hash調度演算法
- 4.5 url_hash調度演算法
- 4.6 least_conn調度演算法
- 五、Nginx負載均衡后端狀態
- 5.1 down
- 5.2 backup
- 5.3 max_conns
- 5.4 max_fails與fail_timeout
- 5.5 keepalive提升吞吐量
一、Nginx負載均衡基本概述
1.1 什么是負載均衡
負載均衡(Load Balance) ,指的是將用戶訪問請求所產生的流量,進行平衡,分攤到多個應用節點處理,負載均衡擴展了應用節點的服務能力,增強了應用服務器的可用性,
1.2 為什么需要負載均衡
當我們的 Web服務器直接面向用戶,往往要承載大量并發請求,單臺服務器難以負荷,我們可以使用多臺 WEB 服務器組成集群,前端使用 Nginx 負載均衡,將請求分散的分發到我們的后端服務器集群中,實作負載的流量分發,從而提升整體性能、以及系統的容災能力,

1.3 負載均衡與代理區別
Nginx 負載均衡與 Nginx 反向代理不同地方在于:Nginx 代理僅代理一臺服務器基于URI來調度,調度到不同功能的應用節點處理,
Nginx 負載均衡則是將客戶端請求通過 proxy_pass 代理到一組 upstream 資源池中處理,
二、Nginx負載均衡應用場景
2.1 四層負載均衡
四層負載均衡指的是 OSI 七層模型中的傳輸層,四層僅需要對客戶端的請求進行TCP/IP協議包代理就可以實作負載均衡,IP+Port四層負載均衡的性能極好、因為只需要底層進行轉發處理,而不需要進行一些復雜的邏輯,

2.2 七層負載均衡
七層負載均衡作業在應用層,它可以完成很多應用方面的協議請求,比如我們說的 http 應用負載均衡,它可以實作 http 頭資訊的改寫、安全應用規則控制、URI 匹配規則控制、及 rewrite 等功能,在應用層里面可以做的內容比較豐富,

2.3 四層負載均衡與七層負載均衡區別
四層負載均衡:傳輸層
優點:性能高,資料包在底層就進行了轉發(LVS),基于LVS的四層代理不需要占用埠,基于nginx的四層代理需要占用埠,
缺點:僅支持ip:prot轉發,無法完成復雜的業務邏輯應用,
七層負載均衡:應用層
優點:貼近業務,支持 URI路徑匹配、Header改寫、Rewrite等
缺點:性能低,資料包需要拆解到頂層才進行調度,消耗隨機埠;
應用場景:MySQL TCP 3306, Redis、SSH、等代理
三、Nginx負載均衡配置
Nginx 實作負載均衡需要兩個模塊:
proxy_pass 代理模塊 (proxy_modules)
upstream 虛擬資源池模塊(proxy_upstream_module)
Syntax: upstream name { ... }
Default: -
Context: http
3.1 負載均衡場景環境準備

地址規劃
| 角色 | 外網IP(NAT) | 內網IP(LAN) | 主機名 |
|---|---|---|---|
| LB01 | eth0:10.0.0.5 | eth1:172.16.1.5 | lb01 |
| web01 | eth0:10.0.0.7 | eth1:172.16.1.7 | web01 |
| web02 | eth0:10.0.0.8 | eth1:172.16.1.8 | web02 |
3.2 后端Web節點配置實體
1.Web01 服務器上配置為應用服務節點, 創建對應 html 檔案
[root@web01 conf.d]# cat web01.conf
server {
listen 80;
server_name web.bertwu.net;
root /code/web;
location / {
index index.html;
}
}
[root@web01 conf.d]# mkdir /code/web
[root@web01 conf.d]# echo 'web01 ip:172.16.1.7' > /code/web/index.html
[root@web01 conf.d]# systemctl restart nginx
2.Web02 服務器上配置為應用服務節點, 創建對應 html 檔案
[root@web02 conf.d]# cat web02.conf
server {
listen 80;
server_name web.bertwu.net;
root /code/web;
location / {
index index.html;
}
}
[root@web02 conf.d]# mkdir /code/web
[root@web02 conf.d]# echo 'web02 ip:172.16.1.8' > /code/web/index.html
[root@web02 conf.d]# systemctl reload nginx
實際生產環境中,每個節點的代碼都一模一樣,這里方便測驗,index.html才寫的不同的內容,
3.3.前端接入Nginx負載均衡
[root@lb01 conf.d]# cat proxy_web.conf
upstream web {
server 172.16.1.7:80;
server 172.16.1.8:80;
}
server {
listen 80;
server_name web.bertwu.net;
location / {
proxy_pass http://web;
include proxy_params;
}
}
[root@lb01 conf.d]# nginx -t
[root@lb01 conf.d]# systemctl reload nginx
proxy_params引數檔案如下:
[root@lb01 nginx]# cat proxy_params
# ip
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# http version
proxy_http_version 1.1;
proxy_set_header Connection "";
# timeout
proxy_connect_timeout 120s;
proxy_read_timeout 120s;
proxy_send_timeout 120s;
# buffer
proxy_buffering on;
proxy_buffer_size 8k;
proxy_buffers 8 8k;
3.4.瀏覽器訪問測驗負載均衡效果
配置本地hosts檔案
10.0.0.5 web.bertwu.net
使用瀏覽器訪問 web.bertwu.com,然后進行重繪測驗,

可以看到,他們交替出現,說明每次請求后負載均衡的確調度到不同的web節點來處理,
3.5 wordpress專案負載均衡配置
# 負載均衡服務器配置
[root@lb01 conf.d]# cat proxy_blog.conf
upstream blog {
server 172.16.1.7:80;
server 172.16.1.8:80;
}
server {
listen 80;
server_name blog.bertwu.net;
location / {
proxy_pass http://blog;
include /etc/nginx/proxy_params;
}
}
后端web服務器代碼不變,
# web01配置
[root@web01 conf.d]# cat wordpress.conf
server {
listen 80;
server_name blog.bertwu.net;
client_max_body_size 100m;
root /code/wordpress;
charset utf-8;
location / {
index index.php index.html;
}
location ~ .*\.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}
}
# web02配置
[root@web02 conf.d]# cat wordpress.conf
server {
listen 80;
server_name blog.bertwu.net;
client_max_body_size 100m;
root /code/wordpress;
charset utf-8;
location / {
index index.php index.html;
}
location ~ .*\.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}
}
四、Nginx負載均衡調度演算法
| 調度演算法 | 概述 |
|---|---|
| 輪詢調度演算法 | 按時間順序逐一分配到不同的后端服務器(默認) |
| weight | 加權輪詢,weight值越大,分配到的訪問幾率越高 |
| ip_hash | 每個請求按訪問IP的hash結果分配(根據節點的個數取模),這樣來自同一IP的固定訪問一個后端服務器 |
| 一致性hash | 不根據節點的個數取模,對232 取模 |
| url_hash | 根據請求uri進行調度到指定節點 |
| least_conn | 將請求傳遞到活動連接數最少的服務器, |
4.1 輪詢調度演算法
輪詢調度演算法的原理是將每一次用戶的請求,輪流分配給內部資源池中的服務器,輪詢演算法的優點是其簡潔性,它無需記錄當前所有連接的狀態,所以它是一種無狀態調度,
upstream web {
server 172.16.1.7:80;
server 172.16.1.8:80;
}
server {
listen 80;
server_name web.bertwu.net;
location / {
proxy_pass http://web;
include proxy_params;
}
}
4.2 加權輪詢調度演算法
輪詢調度演算法沒有考慮每臺服務器的處理能力,在實際情況中,由于每臺服務器的配置、安裝的業務應用等不同,其處理能力會不一樣,所以,我們根據服務器的不同處理能力,給每個服務器分配不同的權值,使其能夠接受相應權值數的服務請求,
```c
upstream web {
server 172.16.1.7:80 weight=5;
server 172.16.1.8:80 weight=1;
}
server {
listen 80;
server_name web.bertwu.net;
location / {
proxy_pass http://web;
include proxy_params;
}
}
4.3 ip_hash調度演算法
ip_hash 是基于用戶請求的IP,對該 IP 進行 hash 運算,根據 hash運算的值,將請求分配到后端特定的一臺節點進行處理,ip_hash 演算法實作公式:hash(ip) % node_counts = index

配置 ip_hash 調度演算法
upstream web {
ip_hash;
server 172.16.1.7:80;
server 172.16.1.8:80;
}
server {
listen 80;
server_name web.bertwu.net;
location / {
proxy_pass http://web;
include proxy_params;
}
}
ip_hash 調度演算法會帶來兩個問題
- 如果有大量來自于同一公網IP的請求會造成某個后端節點流量過大,而其他節點無流量(流量傾斜)
- 如果臨時下線一臺節點,會出現重新計算 hash 值,官方建議將下線節點標記為 down狀態,以保留客戶端IP地址的當前哈希值,(如下圖所示:)

如果有大量的用戶調度到某一節點,而該節點剛好故障,則該演算法會重新計算結果,從而造成大量的用戶被轉移其他節點處理,而需要重新建立會話,
4.4 一致性hash調度演算法
為了規避上述hash情況,一致性hash演算法就誕生,一致性Hash演算法也是使用取模的方法,但不是對服務器節點數量進行取模,而是對2的32方取模,即,一致性Hash演算法將整個Hash空間組織成一個虛擬的圓環,Hash函式值的空間為0 ~ 2^32 - 1,整個哈希環如下:

一致性哈希是順時針的,管增加節點還是下線節點影響的永遠是區域(圓環的某一部分),而不是全域,而ip_hash不管增加節點還是下線節點,都影響的是全域,
在一致性Hash演算法服務節點太少的情況下,容易因為節點分布不均勻面造成資料傾斜(被快取的物件大部分快取在某一臺服務器上)問題

這時我們發現有大量資料集中在節點A上,而節點B只有少量資料,為了解決資料傾斜問題,一致性Hash演算法引入了虛擬節點機制,即對每一個服務器節點計算多個哈希值,每個計算結果位置都放置一個此服務節點,稱為虛擬節點,
具體操作可以為服務器IP或主機名后加入編號來實作,

一致性hash參考檔案
語法:
Syntax: hash key [consistent];
Default: —
Context: upstream
This directive appeared in version 1.7.2.
示例:
```c
upstream web {
# ip_hash; # 基于ip hash取模的方式
hash $remote_addr consistent; # 基于ip的一致性hash
server 172.16.1.7:80;
server 172.16.1.8:80;
}
server {
listen 80;
server_name web.bertwu.net;
location / {
proxy_pass http://web;
include proxy_params;
}
}
注意:ip_hash如果用內網訪問,有課能永遠只會調度到某個節點,不會均攤,這是因為官方給出的解釋:
Specifies that a group should use a load balancing method where requests are distributed between servers based on client IP addresses. The first three octets of the client IPv4 address, or the entire IPv6 address, are used as a hashing key. The method ensures that requests from the same client will always be passed to the same server except when this server is unavailable. In the latter case client requests will be passed to another server. Most probably, it will always be the same server as well
也就是用ip地址的前三段作為key ,如果內網的前三段相同,那么當然算出來的值就相同,這樣就只能調度到特定節點,
4.5 url_hash調度演算法
根據用戶請求的 URL 進行 hash 取模,根據 hash運算的值,將請求分配到后端特定的一臺節點進行處理,URL 演算法使用場景如下:client–>nginx–>url_hash–>cache1–>app
1.用戶請求nginx負載均衡器,通過 url 調度演算法,將請求調度至Cache1
2.由于 Cache1 節點沒有對應的快取資料,則會請求后端獲取,然后回傳資料,并將資料快取起來;
3.當其他用戶再次請求此前相同的 URL 時,此時調度器依然會調度至 Cache1 節點處理;
4.由于 Cache1 節點已存在該URL資源快取,所以直接將快取資料進行回傳;能大幅提升網站的回應;
# 負載均衡服務器配置
root@lb01 conf.d]# cat url_hash.conf
upstream load_pass {
hash $request_uri consistent; # 對uri進行hash,使用一致性hash演算法
server 172.16.1.7:80;
server 172.16.1.8:80;
}
server {
listen 80;
server_name url_hash.bertwu.net;
location / {
proxy_pass http://load_pass;
include /etc/nginx/proxy_params;
}
}
# web01服務器配置
[root@web01 conf.d]# cat url_hash.conf
server {
listen 80;
server_name url_hash.bertwu.net;
root /code/url_hash;
location / {
index index.html;
}
}
[root@web01 conf.d]# mkdir /code/url_hash
[root@web01 conf.d]# cat /code/url_hash/url1.html
web01 url01
[root@web01 conf.d]# cat /code/url_hash/url2.html
web01 url02
# web02服務器配置
[root@web02 conf.d]# cat url_hash.conf
server {
listen 80;
server_name url_hash.bertwu.net;
root /code/url_hash;
location / {
index index.html;
}
}
[root@web01 conf.d]# mkdir /code/url_hashl
[root@web02 ~]# cat /code/url_hash/url1.html
web02 url01
[root@web02 ~]# cat /code/url_hash/url2.html
web02 url02

這樣,訪問http://url_hash.bertwu.net/url1.html,它永遠調度到web02節點進行處理
訪問http://url_hash.bertwu.net/url2.html,它永遠調度到web01節點進行處理
客戶端換任何ip訪問也是一樣,因為它只基于uri調度,
[root@nfs ~]# curl -H Host:url_hash.bertwu.net http://10.0.0.5/url1.html
web02 url01
[root@nfs ~]# curl -H Host:url_hash.bertwu.net http://10.0.0.5/url2.html
web01 url02
4.6 least_conn調度演算法
least_conn調度演算法實作原理,哪臺節點連接數少,則將請求調度至哪臺節點,假設:A節點有1000個連接 ,b節點有500連接,如果此時新的連接進入會分發給b節點
upstream load_pass {
least_conn;
server 172.16.1.7:80;
server 172.16.1.8:80;
}
server {
listen 80;
server_name web.bertwu.net;
location / {
proxy_pass http://load_pass;
include /etc/nginx/proxy_params;
}
}
五、Nginx負載均衡后端狀態
后端 Web 節點在前端 Nginx 負載均衡調度中的狀態如下:
| 狀態 | 概述 |
|---|---|
| down | 當前的server暫時不參與負載均衡 |
| backup | 預留的備份服務器 |
| max_fails | 允許請求失敗的次數 |
| fail_timeout | 經過max_fails失敗后, 服務暫停時間 |
| max_conns | 限制最大的接收連接數 |
5.1 down
[root@lb01 conf.d]# cat proxy_web.conf
upstream web {
server 172.16.1.7:80 down; # 一般用于停機維護
server 172.16.1.8:80;
}
server {
listen 80;
server_name web.bertwu.net;
location / {
proxy_pass http://web;
include proxy_params;
}
}
5.2 backup
backup 將服務器標記為備份服務器,當主服務器不可用時,將請求傳遞至備份服務器處理,
upstream web {
server 172.16.1.7:80;
server 172.16.1.8:80 backup; # 只有所有其他節點故障時候它才啟用
server 172.16.1.9:80;
}
server {
listen 80;
server_name web.bertwu.net;
location / {
proxy_pass http://web;
include proxy_params;
}
}
5.3 max_conns
max_conns 用來限制每個后端節點能夠接收的最大TCP連接數,如果超過此連接則會拋出錯誤,
[root@lb01 conf.d]# cat proxy_web.conf
upstream web {
server 172.16.1.7:80 max_conns=2;
server 172.16.1.8:80 max_conns=2;
}
server {
listen 80;
server_name web.bertwu.net;
location / {
proxy_pass http://web;
include proxy_params;
}
}
通過 jmter 壓力測驗發現,當后端節點處理的連接數非常多的時候,當大于4個連接,其余的連接則會拋出例外,也就是每次僅能滿足4個連接,
5.4 max_fails與fail_timeout
max_fails=2 服務器通信失敗嘗試2次,扔然失敗,認為服務器不可用;fail_timeout=5s 服務器通信失敗后,每5s探測一次節點是否恢復可用;在 fail_timeout設定的時間內,與服務器連接失敗達到 max_fails 則認為服務器不可用;
upstream web {
server 172.16.1.7:80 max_files=2 file_timeout=5s;
server 172.16.1.8:80 max_conns=2 file_timeout=5s;
}
server {
listen 80;
server_name web.bertwu.net;
location / {
proxy_pass http://web;
include proxy_params;
}
}
5.5 keepalive提升吞吐量
keepalive 主要是與后端服務器激活快取,也就是長連接,主要用來提升網站吞吐量,默認情況下:沒有與后端服務啟用長連接功能(http 1.0協議),當有請求時,需要建立連接、維護連接、關閉連接,所以會存在網路消耗,但如果啟用長連接,且將所有的連接都快取了,當連接空閑了又會占用其系統資源,所以可以使用 keepalive 引數來激活快取的同時,還可以使用 keepalive 引數來限制最大的空閑連接數,
配置 Nginx 負載均衡啟用 keepalive 引數:
[root@lb01 conf.d]# cat proxy_web.conf
upstream web {
server 172.16.1.7:80;
server 172.16.1.8:80;
keepalive 16; # 最大空閑連接數,超過就被回收
keepalive_timeout 100s; # 空閑連接的超時時間
}
server {
listen 80;
server_name web.bertwu.net;
location / {
proxy_pass http://web;
#include proxy_params;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $http_host;
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/295136.html
標籤:其他
