Nginx 部署負(fù)載均衡服務(wù)全解析
關(guān)于 Nginx 的配置,松哥之前寫過好幾篇文章和小伙伴們分享了,不過大部分都是基于全局視角去配置的,今天我們就單純來聊一聊用 Nginx 做負(fù)載均衡的配置。
一 什么是負(fù)載均衡
負(fù)載均衡(Load Balancing)是一種計算機網(wǎng)絡(luò)技術(shù),用于將網(wǎng)絡(luò)流量或請求分發(fā)到多個服務(wù)器上,以優(yōu)化資源使用、最大化吞吐量、最小化響應(yīng)時間,并避免任何單一點過載。負(fù)載均衡的目的是確保我們的 Web 應(yīng)用的高可用性和可靠性,同時提高用戶體驗。
圖片
一般來說,我們可能會在如下場景中用到負(fù)載均衡:
- 服務(wù)器負(fù)載均衡:在多個服務(wù)器之間分配網(wǎng)絡(luò)流量,以防止任何單個服務(wù)器因請求過多而性能下降。
- 數(shù)據(jù)中心負(fù)載均衡:在數(shù)據(jù)中心的不同位置或不同數(shù)據(jù)中心之間分配流量,以優(yōu)化資源利用和提高可靠性。
- 云服務(wù)負(fù)載均衡:在云環(huán)境中,負(fù)載均衡可以跨多個虛擬機或容器服務(wù)分配流量。
雖然我們平時做負(fù)載均衡基本上都是 Nginx,但是考慮到文章內(nèi)容的完整性,松哥還是和大家說一說負(fù)載均衡這事可以在不同的網(wǎng)絡(luò)層面實行,比如:
- DNS 負(fù)載均衡:通過 DNS 服務(wù)將域名解析成不同的 IP 地址,將流量分散到不同的服務(wù)器上。
- 硬件負(fù)載均衡:使用專門的硬件設(shè)備(如 F5 BIG-IP)來分配流量。
- 軟件負(fù)載均衡:使用軟件解決方案(如 Nginx、HAProxy)來實現(xiàn)負(fù)載均衡。
- 應(yīng)用層負(fù)載均衡:在應(yīng)用層(如 HTTP/HTTPS)分配請求到不同的服務(wù)器。
- 傳輸層負(fù)載均衡:在傳輸層(如 TCP/UDP)分配連接到不同的服務(wù)器。
二 常見負(fù)載均衡算法
無論你使用哪種工具,在哪進行負(fù)載均衡,常見的負(fù)載均衡算法主要是下面這幾種:
- 輪詢(Round Robin):將請求輪流分配給每臺服務(wù)器。
- 最少連接(Least Connections):將請求分配給當(dāng)前連接數(shù)最少的服務(wù)器。
- 加權(quán)輪詢(Weighted Round Robin):根據(jù)服務(wù)器的性能權(quán)重來分配請求。
- 加權(quán)最少連接(Weighted Least Connections):根據(jù)服務(wù)器的性能權(quán)重和當(dāng)前連接數(shù)來分配請求。
- IP 哈希(IP Hash):根據(jù)客戶端 IP 地址的哈希值來分配請求,以保證來自同一 IP 的請求總是被分配到同一臺服務(wù)器上。
三 Nginx 配置
3.1 輪詢(Round Robin)
輪詢是 Nginx 默認(rèn)的負(fù)載均衡策略,它將客戶端的請求按順序輪流分配到后端服務(wù)器上。如果后端服務(wù)器宕機,Nginx 會自動將其剔除出隊列,直到該服務(wù)器恢復(fù)正常。
舉個栗子:
upstream backend {
server backend1.example.com;
server backend2.example.com;
server backend3.example.com;
}
server {
...
location / {
proxy_pass http://backend;
}
...
}
在上面的配置中,Nginx 會將請求依次分配給 backend1、backend2 和 backend3,循環(huán)往復(fù)。
3.2 加權(quán)輪詢
加權(quán)輪詢策略允許你為后端服務(wù)器分配不同的權(quán)重,權(quán)重越高的服務(wù)器將接收更多的請求。這可以根據(jù)服務(wù)器的硬件配置、處理能力等因素進行靈活配置。
http {
upstream myapp1 { # 定義一個名為myapp1的服務(wù)器組
server backend1.example.com weight=5; # 添加一個服務(wù)器,并設(shè)置權(quán)重為5
server backend2.example.com; # 添加另一個服務(wù)器,權(quán)重默認(rèn)為1
server backend3.example.com down; # 將此服務(wù)器標(biāo)記為down,不參與負(fù)載均衡
server backup1.example.com backup; # 將此服務(wù)器作為備份服務(wù)器
}
server {
listen 80; # 監(jiān)聽80端口
location / { # 匹配所有請求
proxy_pass http://myapp1; # 將請求轉(zhuǎn)發(fā)到myapp1服務(wù)器組
proxy_set_header Host $host; # 設(shè)置請求頭中的Host字段為原始請求的Host
proxy_set_header X-Real-IP $remote_addr; # 設(shè)置請求頭中的X-Real-IP字段為客戶端的真實IP地址
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 設(shè)置請求頭中的X-Forwarded-For字段,以記錄原始請求和代理鏈的IP地址
proxy_set_header X-Forwarded-Proto $scheme; # 設(shè)置請求頭中的X-Forwarded-Proto字段為原始請求的協(xié)議(http或https)
}
}
}
上面的負(fù)載均衡策略是權(quán)重,除了權(quán)重之外,還有輪詢以及 ip_hash 等。
3.3 IP 哈希(IP Hash)
IP 哈希策略根據(jù)客戶端的 IP 地址進行哈希運算,將相同的請求分配給同一個后端服務(wù)器。
這種策略適用于需要保持會話(Session)的場景,因為同一個客戶端的請求會被發(fā)送到同一個服務(wù)器,從而避免了會話信息的丟失。
upstream backend {
ip_hash;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com;
}
server {
...
location / {
proxy_pass http://backend;
}
...
}
在上面的配置中,Nginx 會根據(jù)客戶端的 IP 地址進行哈希運算,然后將請求分配到對應(yīng)的后端服務(wù)器。
3.4 最少連接(Least Connections)
最少連接策略將新的請求分配給當(dāng)前連接數(shù)最少的后端服務(wù)器。這種策略可以確保每個后端服務(wù)器的負(fù)載相對均衡,避免某個服務(wù)器過載而其他服務(wù)器空閑的情況。
注意:Nginx 原生的 Stream 模塊支持最少連接,但在 HTTP 模塊中通常需要借助第三方插件或腳本實現(xiàn)。
對于 HTTP 模塊,可以通過第三方插件如 ngx_http_upstream_fair_module 或編寫 Lua 腳本來實現(xiàn)類似的功能。
但在 Stream 模塊中,可以直接配置,下面是一個 Stream 中配置的例子:
upstream backend {
least_conn;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com;
}
stream {
server {
listen 12345;
proxy_pass backend;
}
}
3.5 健康檢查
在 Nginx 中配置負(fù)載均衡的健康檢查,可以通過主動健康檢查(Active Health Checks)和被動健康檢查(Passive Health Checks)兩種方式來實現(xiàn)。
主動健康檢查
主動健康檢查是定期向上游服務(wù)器發(fā)送請求以檢查其健康狀況,如果上游服務(wù)器未能正確響應(yīng),Nginx 將認(rèn)為該服務(wù)器不健康,并停止向其發(fā)送流量,直到服務(wù)器恢復(fù)健康。
配置方式如下:
http {
upstream backend {
server backend1.example.com;
server backend2.example.com;
check interval=3000 rise=2 fall=5 timeout=1000 type=http;
check_http_send "HEAD /health HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
}
server {
location / {
proxy_pass http://backend;
}
}
}
在這個配置中,Nginx 將每隔 3 秒(interval=3000)向 /health 端點發(fā)送一個 HEAD 請求。如果服務(wù)器連續(xù)兩次返回 2xx 或 3xx 的 HTTP 狀態(tài)碼(rise=2),則認(rèn)為服務(wù)器是健康的。如果服務(wù)器連續(xù)五次未能正確響應(yīng)(fall=5),則認(rèn)為服務(wù)器不健康。
被動健康檢查
被動健康檢查基于實時流量分析,Nginx 根據(jù)后端服務(wù)器的響應(yīng)來判斷其健康狀況。如果服務(wù)器返回特定的錯誤狀態(tài)碼,Nginx 將認(rèn)為該服務(wù)器不健康,并在一段時間內(nèi)不再將請求發(fā)送到該服務(wù)器。
配置方式如下:
http {
upstream backend {
server backend1.example.com;
server backend2.example.com max_fails=2 fail_timeout=30s;
}
server {
listen 80;
location / {
proxy_pass backend;
proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
}
}
}
在這個配置中,如果后端服務(wù)器在 30 秒內(nèi)連續(xù)兩次(max_fails=2)未能正確響應(yīng),它將被臨時從服務(wù)器池中移除。proxy_next_upstream 指令指定了哪些錯誤應(yīng)該觸發(fā)使用不同的服務(wù)器進行重試。