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