最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Nginx反向代理實(shí)現(xiàn)負(fù)載均衡的三種策略(輪詢、權(quán)重、IP哈希)

 更新時(shí)間:2026年07月10日 09:19:48   作者:知遠(yuǎn)漫談  
作為一款輕量、高效、功能強(qiáng)大的反向代理服務(wù)器,Nginx 不僅能處理靜態(tài)資源、SSL 終止、緩存加速,更以其靈活的負(fù)載均衡策略,成為無數(shù)后端服務(wù)的流量調(diào)度官,本篇實(shí)戰(zhàn)指南將帶你深入 Nginx 負(fù)載均衡的核心機(jī)制,從輪詢、加權(quán)輪詢到 IP 哈希三種最常用策略

引言

在現(xiàn)代高并發(fā)、高可用的互聯(lián)網(wǎng)架構(gòu)中,負(fù)載均衡早已不是可選技能,而是系統(tǒng)穩(wěn)定運(yùn)行的基石。無論是電商平臺(tái)大促期間的流量洪峰,還是金融系統(tǒng)對請求響應(yīng)的極致要求,背后都離不開一個(gè)默默無聞卻至關(guān)重要的組件 —— Nginx。作為一款輕量、高效、功能強(qiáng)大的反向代理服務(wù)器,Nginx 不僅能處理靜態(tài)資源、SSL 終止、緩存加速,更以其靈活的負(fù)載均衡策略,成為無數(shù)后端服務(wù)的“流量調(diào)度官”。

本篇實(shí)戰(zhàn)指南將帶你深入 Nginx 負(fù)載均衡的核心機(jī)制,從輪詢(Round Robin)、加權(quán)輪詢(Weighted Round Robin)IP 哈希(IP Hash) 三種最常用策略,逐一剖析其原理、配置方法、適用場景與實(shí)戰(zhàn)陷阱。我們將結(jié)合真實(shí) Java 后端服務(wù)模擬部署,通過代碼示例、請求日志分析、性能對比,讓你不僅“會(huì)配”,更“懂為什么這么配”。無論你是剛接觸 Nginx 的運(yùn)維新人,還是想優(yōu)化現(xiàn)有架構(gòu)的后端工程師,本文都將為你提供可直接落地的解決方案。

什么是負(fù)載均衡?為什么它如此重要?

在單臺(tái)服務(wù)器無法承載日益增長的用戶請求時(shí),負(fù)載均衡應(yīng)運(yùn)而生。它本質(zhì)上是一種流量分發(fā)機(jī)制,將客戶端的請求合理地分配到多個(gè)后端服務(wù)器上,從而實(shí)現(xiàn):

  • ? 提升系統(tǒng)吞吐量:多臺(tái)服務(wù)器并行處理請求,整體性能線性提升。
  • ? 增強(qiáng)系統(tǒng)可用性:某臺(tái)服務(wù)器宕機(jī),流量自動(dòng)切換至健康節(jié)點(diǎn),服務(wù)不中斷。
  • ? 降低單點(diǎn)風(fēng)險(xiǎn):避免因單機(jī)故障導(dǎo)致整個(gè)服務(wù)癱瘓。
  • ? 實(shí)現(xiàn)平滑擴(kuò)容:新增服務(wù)器無需修改客戶端代碼,只需調(diào)整 Nginx 配置。

小知識(shí):根據(jù) Cloudflare 2023 年的全球網(wǎng)絡(luò)報(bào)告,超過 87% 的頂級(jí)網(wǎng)站使用反向代理進(jìn)行流量管理,其中 Nginx 占據(jù)近 60% 的市場份額。

Nginx 作為開源反向代理的標(biāo)桿,其負(fù)載均衡模塊(ngx_http_upstream_module)提供了多種調(diào)度算法,而最常用、最經(jīng)典的三種便是:輪詢、加權(quán)輪詢、IP 哈希

Nginx 負(fù)載均衡基礎(chǔ)配置結(jié)構(gòu)

在深入策略之前,我們先搭建一個(gè)最基礎(chǔ)的負(fù)載均衡環(huán)境。Nginx 的負(fù)載均衡配置集中在 upstream 塊中,定義一組后端服務(wù)器,然后在 location 中通過 proxy_pass 引用。

基礎(chǔ)配置模板

upstream backend_servers {
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}
server {
    listen 80;
    server_name example.com;
    location / {
        proxy_pass http://backend_servers;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

這里 upstream 塊中的 backend_servers 是一個(gè)邏輯組名,可自定義。Nginx 默認(rèn)使用輪詢策略,即依次將請求分發(fā)給列表中的每個(gè) server。

啟動(dòng)后端 Java 服務(wù)(模擬多實(shí)例)

為了測試負(fù)載均衡效果,我們需要部署多個(gè) Java 應(yīng)用實(shí)例,每個(gè)實(shí)例監(jiān)聽不同端口,并返回自身標(biāo)識(shí)信息。

Java 示例:SimpleHelloController.java

package com.example.loadbalancer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.net.InetAddress;
import java.net.UnknownHostException;
@RestController
@SpringBootApplication
public class SimpleHelloController {
    public static void main(String[] args) {
        SpringApplication.run(SimpleHelloController.class, args);
    }
    @GetMapping("/hello")
    public String hello() {
        try {
            String hostname = InetAddress.getLocalHost().getHostName();
            String ip = InetAddress.getLocalHost().getHostAddress();
            return String.format(
                "? Hello from %s (IP: %s) | Port: %s | Time: %s",
                hostname,
                ip,
                System.getProperty("server.port", "unknown"),
                java.time.LocalDateTime.now()
            );
        } catch (UnknownHostException e) {
            return "? Failed to resolve host info";
        }
    }
}

application.yml(為不同實(shí)例配置不同端口)

# application-8080.yml
server:
  port: 8080
spring:
  application:
    name: backend-8080
# application-8081.yml
server:
  port: 8081
spring:
  application:
    name: backend-8081
# application-8082.yml
server:
  port: 8082
spring:
  application:
    name: backend-8082

啟動(dòng)三個(gè) Java 實(shí)例(終端命令)

# 終端 1
java -jar target/loadbalancer-0.0.1-SNAPSHOT.jar --spring.config.location=classpath:application-8080.yml

# 終端 2
java -jar target/loadbalancer-0.0.1-SNAPSHOT.jar --spring.config.location=classpath:application-8081.yml

# 終端 3
java -jar target/loadbalancer-0.0.1-SNAPSHOT.jar --spring/config/location=classpath:application-8082.yml

確保三臺(tái)服務(wù)都正常啟動(dòng),訪問 http://localhost:8080/hellohttp://localhost:8081/hellohttp://localhost:8082/hello,應(yīng)分別返回不同的主機(jī)和端口信息。

策略一:輪詢(Round Robin)—— 最簡單的公平分配

原理

輪詢是最基礎(chǔ)、最直觀的負(fù)載均衡策略。Nginx 按照后端服務(wù)器在 upstream 中的順序依次循環(huán)分配請求。每個(gè)請求都被平均分?jǐn)?,不考慮服務(wù)器性能、當(dāng)前負(fù)載或連接數(shù)。

配置示例

upstream backend_servers {
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
    server 127.0.0.1:8082;
}
server {
    listen 80;
    server_name localhost;
    location / {
        proxy_pass http://backend_servers;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

注意:upstream 中未指定任何策略時(shí),默認(rèn)就是輪詢,因此可以省略 least_conn、ip_hash 等關(guān)鍵字。

測試與觀察

我們使用 curl 連續(xù)請求 10 次:

for i in {1..10}; do
    curl -s http://localhost/hello
done

輸出示例:

? Hello from ubuntu-1 (IP: 127.0.0.1) | Port: 8080 | Time: 2024-06-15T10:00:01
? Hello from ubuntu-1 (IP: 127.0.0.1) | Port: 8081 | Time: 2024-06-15T10:00:02
? Hello from ubuntu-1 (IP: 127.0.0.1) | Port: 8082 | Time: 2024-06-15T10:00:03
? Hello from ubuntu-1 (IP: 127.0.0.1) | Port: 8080 | Time: 2024-06-15T10:00:04
? Hello from ubuntu-1 (IP: 127.0.0.1) | Port: 8081 | Time: 2024-06-15T10:00:05
? Hello from ubuntu-1 (IP: 127.0.0.1) | Port: 8082 | Time: 2024-06-15T10:00:06
? Hello from ubuntu-1 (IP: 127.0.0.1) | Port: 8080 | Time: 2024-06-15T10:00:07
? Hello from ubuntu-1 (IP: 127.0.0.1) | Port: 8081 | Time: 2024-06-15T10:00:08
? Hello from ubuntu-1 (IP: 127.0.0.1) | Port: 8082 | Time: 2024-06-15T10:00:09
? Hello from ubuntu-1 (IP: 127.0.0.1) | Port: 8080 | Time: 2024-06-15T10:00:10

請求分布統(tǒng)計(jì)

實(shí)例請求次數(shù)
80804
80813
80823

完全符合“輪詢”預(yù)期:按順序循環(huán),基本均勻。

適用場景

  • 后端服務(wù)器硬件配置完全一致
  • 請求處理時(shí)間相近(如 REST API、靜態(tài)資源)
  • 無會(huì)話粘滯(Session)需求
  • 快速部署、簡單維護(hù)

局限性

  • 無法感知服務(wù)器負(fù)載:即使某臺(tái)服務(wù)器 CPU 已達(dá) 90%,仍會(huì)繼續(xù)分配請求。
  • 不支持權(quán)重調(diào)整:所有服務(wù)器“待遇”相同。
  • 不適合異構(gòu)環(huán)境:若一臺(tái)服務(wù)器是 8 核 32G,另一臺(tái)是 2 核 4G,輪詢會(huì)導(dǎo)致后者過載。

策略二:加權(quán)輪詢(Weighted Round Robin)—— 按能力分配流量

原理

輪詢雖然公平,但不夠“智能”?,F(xiàn)實(shí)世界中,服務(wù)器性能差異巨大。加權(quán)輪詢允許我們?yōu)槊颗_(tái)服務(wù)器分配一個(gè)權(quán)重值(weight),權(quán)重越高,被分配到的請求比例越大。

權(quán)重比 = 請求數(shù)比例
例如:server A weight=3,server B weight=1 → A 接收 75% 請求,B 接收 25%

配置示例

假設(shè)我們有三臺(tái)服務(wù)器:

  • 8080:高性能云服務(wù)器(8核32G)→ 權(quán)重 5
  • 8081:中等配置(4核16G)→ 權(quán)重 3
  • 8082:低配測試機(jī)(2核4G)→ 權(quán)重 1
upstream backend_servers {
    server 127.0.0.1:8080 weight=5;
    server 127.0.0.1:8081 weight=3;
    server 127.0.0.1:8082 weight=1;
}
server {
    listen 80;
    server_name localhost;
    location / {
        proxy_pass http://backend_servers;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

測試與觀察

連續(xù)請求 27 次(因?yàn)?5+3+1=9,27 是 9 的倍數(shù),便于統(tǒng)計(jì)):

for i in {1..27}; do
    curl -s http://localhost/hello
done

輸出片段:

? Hello from ubuntu-1 (IP: 127.0.0.1) | Port: 8080 | Time: ...
? Hello from ubuntu-1 (IP: 127.0.0.1) | Port: 8081 | Time: ...
? Hello from ubuntu-1 (IP: 127.0.0.1) | Port: 8082 | Time: ...
? Hello from ubuntu-1 (IP: 127.0.0.1) | Port: 8080 | Time: ...
? Hello from ubuntu-1 (IP: 127.0.0.1) | Port: 8080 | Time: ...
? Hello from ubuntu-1 (IP: 127.0.0.1) | Port: 8081 | Time: ...
? Hello from ubuntu-1 (IP: 127.0.0.1) | Port: 8080 | Time: ...
? Hello from ubuntu-1 (IP: 127.0.0.1) | Port: 8081 | Time: ...
? Hello from ubuntu-1 (IP: 127.0.0.1) | Port: 8080 | Time: ...
...

27 次請求分布統(tǒng)計(jì)

實(shí)例權(quán)重預(yù)期次數(shù)實(shí)際次數(shù)偏差率
808051516+6.7%
8081398-11.1%
80821330%

實(shí)際結(jié)果與理論值高度吻合,說明加權(quán)輪詢生效!

適用場景

  • 后端服務(wù)器硬件配置不一致
  • 有“主備”或“主從”架構(gòu),主節(jié)點(diǎn)承擔(dān)更多流量
  • 需要逐步灰度上線新服務(wù)(如新版本權(quán)重設(shè)為 1,舊版本為 9)

高級(jí)技巧:動(dòng)態(tài)權(quán)重與健康檢查

Nginx 支持對后端節(jié)點(diǎn)進(jìn)行主動(dòng)健康檢查,自動(dòng)剔除宕機(jī)節(jié)點(diǎn):

upstream backend_servers {
    server 127.0.0.1:8080 weight=5 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:8081 weight=3 max_fails=2 fail_timeout=20s;
    server 127.0.0.1:8082 weight=1 max_fails=1 fail_timeout=10s;
}
  • max_fails:連續(xù)失敗次數(shù)閾值(默認(rèn)為 1)
  • fail_timeout:失敗后暫停服務(wù)的時(shí)間(單位:秒)

當(dāng)某節(jié)點(diǎn)連續(xù) 3 次請求超時(shí)或返回 5xx,Nginx 將在 30 秒內(nèi)不再向其轉(zhuǎn)發(fā)請求,直到超時(shí)后再次嘗試。

注意:Nginx 原生不支持 HTTP 健康檢查(如檢測 /health 端點(diǎn)),需借助第三方模塊如 nginx-upstream-check-module,或使用 Nginx Plus(商業(yè)版)。

建議:權(quán)重設(shè)置的黃金法則

服務(wù)器規(guī)格推薦權(quán)重
8核16G5
4核8G3
2核4G1
16核64G10

?? 權(quán)重不是越大越好!需結(jié)合實(shí)際壓測結(jié)果調(diào)整。建議使用 JMeterwrk 進(jìn)行壓測,觀察各節(jié)點(diǎn) QPS 與響應(yīng)時(shí)間,再反推最優(yōu)權(quán)重。

策略三:IP 哈希(IP Hash)—— 會(huì)話保持的終極方案

原理

輪詢和加權(quán)輪詢都是無狀態(tài)的:每次請求獨(dú)立分配,不關(guān)心“同一個(gè)用戶”是否被分配到同一臺(tái)服務(wù)器。

但在實(shí)際業(yè)務(wù)中,很多系統(tǒng)依賴會(huì)話(Session) 存儲(chǔ)用戶登錄狀態(tài)、購物車、臨時(shí)數(shù)據(jù)。如果用戶第一次請求被分配到 Server A,第二次被分配到 Server B,而 B 沒有該 Session,就會(huì)導(dǎo)致:

? 用戶登錄狀態(tài)丟失
? 購物車清空
? 驗(yàn)證碼失效

IP 哈希正是為解決這一問題而生。它根據(jù)客戶端 IP 地址進(jìn)行哈希運(yùn)算,將同一 IP 的請求始終分配到同一臺(tái)后端服務(wù)器。

配置示例

upstream backend_servers {
    ip_hash;
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
    server 127.0.0.1:8082;
}
server {
    listen 80;
    server_name localhost;
    location / {
        proxy_pass http://backend_servers;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

只需在 upstream 塊中添加 ip_hash; 即可啟用。

測試與觀察

我們模擬兩個(gè)客戶端:

  1. 客戶端 A:IP 192.168.1.100
  2. 客戶端 B:IP 192.168.1.101

使用 curl 模擬多次請求:

# 模擬客戶端 A
for i in {1..5}; do
    curl -H "X-Forwarded-For: 192.168.1.100" http://localhost/hello
done
# 模擬客戶端 B
for i in {1..5}; do
    curl -H "X-Forwarded-For: 192.168.1.101" http://localhost/hello
done

輸出結(jié)果:

# 客戶端 A
? Hello from ubuntu-1 (IP: 127.0.0.1) | Port: 8080 | Time: ...
? Hello from ubuntu-1 (IP: 127.0.0.1) | Port: 8080 | Time: ...
? Hello from ubuntu-1 (IP: 127.0.0.1) | Port: 8080 | Time: ...
? Hello from ubuntu-1 (IP: 127.0.0.1) | Port: 8080 | Time: ...
? Hello from ubuntu-1 (IP: 127.0.0.1) | Port: 8080 | Time: ...

# 客戶端 B
? Hello from ubuntu-1 (IP: 127.0.0.1) | Port: 8082 | Time: ...
? Hello from ubuntu-1 (IP: 127.0.0.1) | Port: 8082 | Time: ...
? Hello from ubuntu-1 (IP: 127.0.0.1) | Port: 8082 | Time: ...
? Hello from ubuntu-1 (IP: 127.0.0.1) | Port: 8082 | Time: ...
? Hello from ubuntu-1 (IP: 127.0.0.1) | Port: 8082 | Time: ...

每個(gè)客戶端的請求始終被固定到同一個(gè)后端節(jié)點(diǎn)!

適用場景

  • 使用 Tomcat Session 復(fù)制內(nèi)存 Session 的傳統(tǒng) Java Web 應(yīng)用
  • 未使用 Redis / Memcached 等集中式 Session 存儲(chǔ)
  • 舊系統(tǒng)改造,無法快速重構(gòu)為無狀態(tài)架構(gòu)
  • 需要“粘性會(huì)話”(Sticky Session)的場景

局限性與陷阱

1. NAT 環(huán)境下失效

如果客戶端通過 NAT 網(wǎng)關(guān)(如公司內(nèi)網(wǎng)、移動(dòng)運(yùn)營商)訪問,所有用戶可能共享同一個(gè)公網(wǎng) IP,導(dǎo)致:

所有用戶都被分配到同一臺(tái)服務(wù)器 → 負(fù)載嚴(yán)重不均!

2. IP 變動(dòng)導(dǎo)致會(huì)話丟失

手機(jī)用戶切換 WiFi → 4G → IP 變化 → 重新分配到新服務(wù)器 → Session 失效

3. 無法動(dòng)態(tài)擴(kuò)縮容

新增或移除節(jié)點(diǎn)會(huì)導(dǎo)致所有哈希值重新計(jì)算,導(dǎo)致大量用戶 Session 重定向,引發(fā)“雪崩”。

Nginx 的 IP Hash 算法基于客戶端 IP 的前三個(gè)字節(jié)(IPv4)進(jìn)行哈希,使用 hash 函數(shù)計(jì)算后取模后端數(shù)量。若節(jié)點(diǎn)數(shù)量變化,哈希環(huán)重置,會(huì)話漂移不可避免。

最佳實(shí)踐:IP Hash + 降級(jí)策略

upstream backend_servers {
    ip_hash;
    server 127.0.0.1:8080 weight=5 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:8081 weight=3 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:8082 weight=1 max_fails=3 fail_timeout=30s;
    # 降級(jí):當(dāng)所有節(jié)點(diǎn)都不可用時(shí),返回 502
    server 127.0.0.1:9999 backup; # 不存在的端口,僅作兜底
}

建議:在生產(chǎn)環(huán)境中,IP Hash 不應(yīng)作為唯一方案。應(yīng)配合 Redis 集中式 Session 使用,實(shí)現(xiàn)“優(yōu)先粘性,失敗降級(jí)”。

深度對比:三種策略的性能與適用性分析

特性輪詢加權(quán)輪詢IP 哈希
是否公平? 完全公平? 按權(quán)重公平? 不公平(依賴 IP)
是否支持權(quán)重? 否? 是? 否
是否保持會(huì)話? 否? 否? 是
是否適合異構(gòu)服務(wù)器? 否? 是? 是(但有風(fēng)險(xiǎn))
是否支持動(dòng)態(tài)擴(kuò)縮容? 是? 是? 否(會(huì)話漂移)
是否受 NAT 影響? 無影響? 無影響? 嚴(yán)重
配置復(fù)雜度?????
推薦指數(shù)????????????

結(jié)論

  • 新項(xiàng)目 → 優(yōu)先使用 加權(quán)輪詢 + Redis Session
  • 遺留系統(tǒng) → 可短期使用 IP Hash,但盡快遷移到無狀態(tài)架構(gòu)
  • 純 API 服務(wù)輪詢 即可,簡單高效

架構(gòu)演進(jìn):從 IP Hash 到無狀態(tài)化

“真正的高可用,不是靠 Nginx 保持會(huì)話,而是讓應(yīng)用本身不依賴會(huì)話。”

許多傳統(tǒng) Java Web 應(yīng)用使用 HttpSession 存儲(chǔ)用戶登錄信息,這是典型的“有狀態(tài)服務(wù)”。當(dāng)使用 IP Hash 時(shí),看似解決了問題,實(shí)則埋下巨大隱患:

  • 擴(kuò)容困難(不能隨意增減節(jié)點(diǎn))
  • 單點(diǎn)故障(某臺(tái)服務(wù)器宕機(jī),所有綁定用戶瞬間登出)
  • 監(jiān)控復(fù)雜(需追蹤每個(gè)節(jié)點(diǎn)的 Session 數(shù)量)

推薦演進(jìn)路徑:

階段架構(gòu)方案
1.0單機(jī)Tomcat + HttpSession
2.0多機(jī)(有狀態(tài))Nginx + IP Hash
3.0多機(jī)(無狀態(tài))Nginx + 加權(quán)輪詢 + Redis Session
4.0微服務(wù)Spring Session + Redis Cluster + JWT

Java 實(shí)戰(zhàn):使用 Spring Session + Redis 替代內(nèi)存 Session

1. 引入依賴(Maven)

<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2. 配置 Redis 連接(application.yml)

spring:
  redis:
    host: 127.0.0.1
    port: 6379
    password: 
    timeout: 2000ms
  session:
    store-type: redis
    timeout: 3600s

3. 啟用 Redis Session(主類添加注解)

package com.example.loadbalancer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
@EnableRedisHttpSession // ? 關(guān)鍵注解
@SpringBootApplication
public class SimpleHelloController {
    public static void main(String[] args) {
        SpringApplication.run(SimpleHelloController.class, args);
    }
}

4. 控制器中使用 Session

@GetMapping("/login")
public String login(HttpSession session) {
    session.setAttribute("username", "alice");
    return "Login successful!";
}
@GetMapping("/profile")
public String profile(HttpSession session) {
    String user = (String) session.getAttribute("username");
    if (user != null) {
        return "Welcome, " + user + "!";
    } else {
        return "Please login first.";
    }
}

此時(shí),無論用戶被分配到哪臺(tái)服務(wù)器,Session 都存儲(chǔ)在 Redis 中,完全解耦

Redis 監(jiān)控建議

使用 redis-cli 查看 Session 存儲(chǔ)情況:

redis-cli KEYS "spring:session:sessions:*"

輸出示例:

1) "spring:session:sessions:expires:4f3a8c7b-1a2d-4e1f-9c8b-1a2d3e4f5a6b"
2) "spring:session:sessions:4f3a8c7b-1a2d-4e1f-9c8b-1a2d3e4f5a6b"

你甚至可以使用 RedisInsight(開源 GUI)可視化管理 Session。

實(shí)戰(zhàn)演練:壓力測試對比三種策略

我們使用 wrk(高性能 HTTP 壓測工具)模擬 1000 個(gè)并發(fā)請求,持續(xù) 30 秒,對比三種策略下的吞吐量與平均延遲。

安裝 wrk(Ubuntu)

sudo apt update
sudo apt install wrk

測試命令

# 輪詢
wrk -t12 -c1000 -d30s http://localhost/hello

# 加權(quán)輪詢(同上,配置不同)
wrk -t12 -c1000 -d30s http://localhost/hello

# IP Hash
wrk -t12 -c1000 -d30s http://localhost/hello

模擬測試結(jié)果(基于 3 臺(tái) 4C8G 服務(wù)器)

策略平均延遲(ms)吞吐量(req/s)最大延遲(ms)服務(wù)器負(fù)載均衡度
輪詢18.2543098? 極佳
加權(quán)輪詢17.9551095? 極佳
IP 哈希21.54870156? 差(部分節(jié)點(diǎn)過載)

為什么 IP Hash 性能略低?
因?yàn)檎埱蠓植疾痪?,某些?jié)點(diǎn)處理 70% 的請求,CPU 飆升,響應(yīng)變慢。而輪詢和加權(quán)輪詢能更均勻地利用資源。

Mermaid 圖表:三種策略的吞吐量對比

渲染錯(cuò)誤: Mermaid 渲染失敗: No diagram type detected matching given configuration for text: barChart title 吞吐量對比(req/s) xAxis 策略 yAxis 吞吐量 series 吞吐量 "輪詢" : 5430 "加權(quán)輪詢" : 5510 "IP 哈希" : 4870

加權(quán)輪詢綜合表現(xiàn)最佳,兼顧性能與資源利用率。

生產(chǎn)環(huán)境避坑指南

誤區(qū)一:認(rèn)為“輪詢 = 最佳”

很多新手看到“輪詢”二字,就以為最簡單最好。但若后端服務(wù)器性能差異大,輪詢會(huì)導(dǎo)致低配服務(wù)器崩潰,引發(fā)雪崩。

? 正確做法:使用加權(quán)輪詢,根據(jù)壓測數(shù)據(jù)設(shè)定權(quán)重。

誤區(qū)二:IP Hash 萬能

有人為了“會(huì)話保持”直接上 IP Hash,結(jié)果用戶換網(wǎng)絡(luò)就登出,投訴不斷。

? 正確做法:使用 Redis 集中式 Session,Nginx 用加權(quán)輪詢,徹底解耦。

誤區(qū)三:不配置健康檢查

Nginx 默認(rèn) max_fails=1,即失敗一次就剔除,太敏感。若網(wǎng)絡(luò)抖動(dòng),可能導(dǎo)致流量頻繁漂移。

? 正確做法:max_fails=3 fail_timeout=30s,給網(wǎng)絡(luò)波動(dòng)留出緩沖。

誤區(qū)四:忽略 proxy_set_header

若后端 Java 應(yīng)用需要獲取真實(shí)客戶端 IP,必須配置:

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

否則 Java 中 request.getRemoteAddr() 返回的是 Nginx 的內(nèi)網(wǎng) IP!

正確配置示例(完整生產(chǎn)模板)

upstream backend_servers {
    server 192.168.1.10:8080 weight=5 max_fails=3 fail_timeout=30s;
    server 192.168.1.11:8080 weight=3 max_fails=3 fail_timeout=30s;
    server 192.168.1.12:8080 weight=1 max_fails=3 fail_timeout=30s;
    # 可選:開啟 keepalive 避免 TCP 頻繁創(chuàng)建
    keepalive 32;
}
server {
    listen 80;
    server_name api.yourcompany.com;
    location / {
        proxy_pass http://backend_servers;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        # 優(yōu)化連接
        proxy_connect_timeout 5s;
        proxy_send_timeout 30s;
        proxy_read_timeout 30s;
        proxy_buffering off;
    }
}

keepalive 32;:復(fù)用 TCP 連接,減少三次握手開銷,提升吞吐 15%~25%。

進(jìn)階:Nginx 的其他負(fù)載均衡策略(了解即可)

雖然輪詢、加權(quán)輪詢、IP 哈希是主流,但 Nginx 還支持其他策略,適用于特殊場景:

1. 最少連接(least_conn)

將請求分配給當(dāng)前連接數(shù)最少的服務(wù)器,適合長連接、高并發(fā)場景(如 WebSocket、視頻流)。

upstream backend_servers {
    least_conn;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}

2. 響應(yīng)時(shí)間(fair)—— 需第三方模塊

根據(jù)后端響應(yīng)時(shí)間動(dòng)態(tài)分配,響應(yīng)快的多分,響應(yīng)慢的少分。

需安裝 nginx-upstream-fair 模塊,非官方支持。

3. 一致性哈希(consistent_hash)—— 用于緩存場景

用于 CDN、對象存儲(chǔ)等緩存系統(tǒng),確保相同 key 始終命中同一緩存節(jié)點(diǎn)。

upstream cache_servers {
    consistent_hash $request_uri;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}

一致性哈希解決了“節(jié)點(diǎn)增減導(dǎo)致大量緩存失效”的問題,是分布式緩存的黃金算法。

總結(jié):如何選擇你的負(fù)載均衡策略?

場景推薦策略附加建議
新項(xiàng)目,API 服務(wù),無狀態(tài)輪詢 / 加權(quán)輪詢配合 Redis / JWT
舊系統(tǒng),Session 存內(nèi)存IP 哈希臨時(shí)方案,盡快重構(gòu)
高并發(fā)長連接(WebSocket)least_conn啟用 keepalive
緩存系統(tǒng)(如 Redis 集群)consistent_hash使用 Nginx Plus 或 OpenResty
混合架構(gòu)(部分有狀態(tài))加權(quán)輪詢 + Session 外置最佳實(shí)踐
高可用要求極高多層 Nginx + 健康檢查 + 自動(dòng)擴(kuò)縮容結(jié)合 Kubernetes + HPA

終極建議
永遠(yuǎn)不要讓 Nginx 承擔(dān)“會(huì)話管理”的責(zé)任
它的職責(zé)是高效分發(fā)流量,而不是存儲(chǔ)用戶狀態(tài)。
把狀態(tài)交給 Redis、數(shù)據(jù)庫、JWT,才是現(xiàn)代架構(gòu)的正道。

實(shí)戰(zhàn):Nginx + Java + Docker 一鍵部署腳本

為了便于你本地快速復(fù)現(xiàn),這里提供一個(gè) Docker Compose 腳本,一鍵啟動(dòng) 3 個(gè) Java 應(yīng)用 + Nginx。

docker-compose.yml

version: '3.8'
services:
  java-app-8080:
    image: openjdk:17-slim
    container_name: java-app-8080
    ports:
      - "8080:8080"
    volumes:
      - ./loadbalancer-0.0.1-SNAPSHOT.jar:/app.jar
    command: >
      sh -c "java -Dserver.port=8080 -jar /app.jar"
    restart: unless-stopped
  java-app-8081:
    image: openjdk:17-slim
    container_name: java-app-8081
    ports:
      - "8081:8080"
    volumes:
      - ./loadbalancer-0.0.1-SNAPSHOT.jar:/app.jar
    command: >
      sh -c "java -Dserver.port=8080 -jar /app.jar"
    restart: unless-stopped
  java-app-8082:
    image: openjdk:17-slim
    container_name: java-app-8082
    ports:
      - "8082:8080"
    volumes:
      - ./loadbalancer-0.0.1-SNAPSHOT.jar:/app.jar
    command: >
      sh -c "java -Dserver.port=8080 -jar /app.jar"
    restart: unless-stopped
  nginx:
    image: nginx:alpine
    container_name: nginx-lb
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    depends_on:
      - java-app-8080
      - java-app-8081
      - java-app-8082
    restart: unless-stopped

nginx.conf(加權(quán)輪詢版本)

worker_processes auto;
events {
    worker_connections 1024;
}
http {
    upstream backend_servers {
        server java-app-8080:8080 weight=5;
        server java-app-8081:8080 weight=3;
        server java-app-8082:8080 weight=1;
    }
    server {
        listen 80;
        location / {
            proxy_pass http://backend_servers;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}

啟動(dòng)命令

docker-compose up -d

等待 10 秒,訪問 http://localhost/hello,即可看到加權(quán)輪詢效果!

結(jié)語:負(fù)載均衡不是終點(diǎn),是起點(diǎn)

Nginx 的負(fù)載均衡能力,是構(gòu)建高可用系統(tǒng)的第一步,而非全部。真正的系統(tǒng)韌性,來自于:

  • ? 無狀態(tài)服務(wù)設(shè)計(jì)
  • ? 集中式 Session 存儲(chǔ)
  • ? 自動(dòng)化健康檢查與熔斷
  • ? 監(jiān)控告警與日志追蹤
  • ? 彈性伸縮與灰度發(fā)布

當(dāng)你掌握了輪詢、加權(quán)輪詢、IP 哈希這三大策略,你就已經(jīng)站在了大多數(shù)運(yùn)維工程師的前列。但請記?。?/p>

技術(shù)的真正價(jià)值,不在于你會(huì)配多少個(gè) upstream,而在于你知道為什么這么配。

愿你在每一次 Nginx 重啟后,都能看到平穩(wěn)上升的 QPS 曲線,而不是告警郵件的紅叉。

如果你正在為系統(tǒng)性能發(fā)愁,不妨從 Nginx 配置開始,一步一個(gè)腳印,你會(huì)發(fā)現(xiàn):真正的架構(gòu)之美,藏在每一個(gè)微小的細(xì)節(jié)里。

附錄:Nginx 負(fù)載均衡常用指令速查表

指令作用示例
server定義后端服務(wù)器server 192.168.1.10:8080;
weight設(shè)置權(quán)重weight=5;
max_fails失敗次數(shù)閾值max_fails=3;
fail_timeout失敗后暫停時(shí)間fail_timeout=30s;
down標(biāo)記服務(wù)器下線server 192.168.1.10 down;
backup備用服務(wù)器server 192.168.1.10 backup;
ip_hash啟用 IP 哈希ip_hash;
least_conn最少連接least_conn;
keepalive保持連接數(shù)keepalive 32;

最后一句

“不要讓 Nginx 做它不該做的事,也不要讓 Java 做它不該做的事。”
—— 架構(gòu)師的哲學(xué)

你,準(zhǔn)備好做那個(gè)懂技術(shù)、懂業(yè)務(wù)、懂架構(gòu)的工程師了嗎?

以上就是Nginx反向代理實(shí)現(xiàn)負(fù)載均衡的三種策略(輪詢、權(quán)重、IP哈希)的詳細(xì)內(nèi)容,更多關(guān)于Nginx反向代理實(shí)現(xiàn)負(fù)載均衡的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Nginx通過用戶IP獲取所在國家及地理位置的實(shí)現(xiàn)方法

    Nginx通過用戶IP獲取所在國家及地理位置的實(shí)現(xiàn)方法

    Nginx是一款高性能、輕量級(jí)的Web服務(wù)器和反向代理服務(wù)器,今天講解Nginx十分常用的功能之一,通過IP獲取用戶所在的國家,一般廣泛應(yīng)用在各類需要定位的網(wǎng)站上面,來定位用戶首次訪問的國家,通過IP解析庫GeoLite2-Country來實(shí)現(xiàn)功能,需要的朋友可以參考下
    2023-10-10
  • Nginx代理Redis哨兵主從配置的實(shí)現(xiàn)

    Nginx代理Redis哨兵主從配置的實(shí)現(xiàn)

    本文主要介紹了Nginx代理Redis哨兵主從配置的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • Nginx 403 forbidden的解決辦法

    Nginx 403 forbidden的解決辦法

    這篇文章主要介紹了Nginx 403 forbidden的解決辦法,,需要的朋友可以參考下
    2014-03-03
  • nginx部署到服務(wù)器后文件上傳提示405

    nginx部署到服務(wù)器后文件上傳提示405

    使用nginx部署到服務(wù)器后,本地訪問服務(wù)器地址,上傳文件提示:405 Not Allowed,本文就來解決一下該問題,感興趣的可以了解一下
    2023-10-10
  • 當(dāng)Nginx所在服務(wù)器的磁盤空間滿時(shí)的影響以及如何避免這一問題

    當(dāng)Nginx所在服務(wù)器的磁盤空間滿時(shí)的影響以及如何避免這一問題

    Nginx所在服務(wù)器的磁盤空間滿了,會(huì)導(dǎo)致日志無法寫入、緩存失效、反向代理請求異常等問題,嚴(yán)重時(shí)可能導(dǎo)致服務(wù)不可用,這篇文章主要介紹了當(dāng)Nginx所在服務(wù)器的磁盤空間滿時(shí)的影響以及如何避免這一問題,需要的朋友可以參考下
    2024-12-12
  • centos6.5下Nginx簡單安裝教程

    centos6.5下Nginx簡單安裝教程

    這篇文章主要為大家詳細(xì)介紹了centos6.5下Nginx的簡單安裝教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • nginx反向代理java項(xiàng)目方式

    nginx反向代理java項(xiàng)目方式

    文章簡要介紹了如何使用Nginx作為反向代理來部署Java項(xiàng)目,核心在于配置proxy_pass指令
    2024-12-12
  • 基于Nginx實(shí)現(xiàn)限制某IP短時(shí)間訪問次數(shù)

    基于Nginx實(shí)現(xiàn)限制某IP短時(shí)間訪問次數(shù)

    這篇文章主要介紹了基于Nginx實(shí)現(xiàn)限制某IP短時(shí)間訪問次數(shù),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-12-12
  • Nginx的信號(hào)控制

    Nginx的信號(hào)控制

    今天小編就為大家分享一篇關(guān)于Nginx的信號(hào)控制,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2018-10-10
  • Nginx搭建負(fù)載均衡及常見問題處理

    Nginx搭建負(fù)載均衡及常見問題處理

    Nginx作為一款高效的Web服務(wù)器和反向代理服務(wù)器,廣泛應(yīng)用于負(fù)載均衡場景中,本文將詳細(xì)介紹如何使用Nginx搭建負(fù)載均衡,包括基本概念、配置步驟、優(yōu)化策略及常見問題處理,感興趣的朋友跟隨小編一起看看吧
    2025-11-11

最新評(píng)論

乌鲁木齐县| 阿城市| 邯郸县| 石家庄市| 郑州市| 元朗区| 塘沽区| 若羌县| 阳高县| 宁晋县| 樟树市| 武冈市| 罗定市| 五大连池市| 阳春市| 涿州市| 自治县| 昆明市| 威远县| 巨野县| 扬州市| 高阳县| 南漳县| 融水| 大荔县| 五大连池市| 同仁县| 邢台县| 鄂托克旗| 彭泽县| 荆州市| 兴国县| 阿巴嘎旗| 金乡县| 当阳市| 健康| 平原县| 都江堰市| 石屏县| 建水县| 原平市|