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

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

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

引言

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

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

什么是負載均衡?為什么它如此重要?

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

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

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

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

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

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

基礎配置模板

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 是一個邏輯組名,可自定義。Nginx 默認使用輪詢策略,即依次將請求分發(fā)給列表中的每個 server。

啟動后端 Java 服務(模擬多實例)

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

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(為不同實例配置不同端口)

# 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

啟動三個 Java 實例(終端命令)

# 終端 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

確保三臺服務都正常啟動,訪問 http://localhost:8080/hellohttp://localhost:8081/hello、http://localhost:8082/hello,應分別返回不同的主機和端口信息。

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

原理

輪詢是最基礎、最直觀的負載均衡策略。Nginx 按照后端服務器在 upstream 中的順序依次循環(huán)分配請求。每個請求都被平均分攤,不考慮服務器性能、當前負載或連接數(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 中未指定任何策略時,默認就是輪詢,因此可以省略 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)計

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

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

適用場景

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

局限性

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

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

原理

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

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

配置示例

假設我們有三臺服務器:

  • 8080:高性能云服務器(8核32G)→ 權(quán)重 5
  • 8081:中等配置(4核16G)→ 權(quán)重 3
  • 8082:低配測試機(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 次(因為 5+3+1=9,27 是 9 的倍數(shù),便于統(tǒng)計):

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)計

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

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

適用場景

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

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

Nginx 支持對后端節(jié)點進行主動健康檢查,自動剔除宕機節(jié)點:

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ù)閾值(默認為 1)
  • fail_timeout:失敗后暫停服務的時間(單位:秒)

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

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

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

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

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

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

原理

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

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

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

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

配置示例

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; 即可啟用。

測試與觀察

我們模擬兩個客戶端:

  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: ...

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

適用場景

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

局限性與陷阱

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

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

所有用戶都被分配到同一臺服務器 → 負載嚴重不均!

2. IP 變動導致會話丟失

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

3. 無法動態(tài)擴縮容

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

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

最佳實踐:IP Hash + 降級策略

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;
    # 降級:當所有節(jié)點都不可用時,返回 502
    server 127.0.0.1:9999 backup; # 不存在的端口,僅作兜底
}

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

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

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

結(jié)論

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

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

“真正的高可用,不是靠 Nginx 保持會話,而是讓應用本身不依賴會話。”

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

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

推薦演進路徑:

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

Java 實戰(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.";
    }
}

此時,無論用戶被分配到哪臺服務器,Session 都存儲在 Redis 中,完全解耦!

Redis 監(jiān)控建議

使用 redis-cli 查看 Session 存儲情況:

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。

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

我們使用 wrk(高性能 HTTP 壓測工具)模擬 1000 個并發(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 臺 4C8G 服務器)

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

為什么 IP Hash 性能略低?
因為請求分布不均,某些節(jié)點處理 70% 的請求,CPU 飆升,響應變慢。而輪詢和加權(quán)輪詢能更均勻地利用資源。

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

渲染錯誤: 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ū)一:認為“輪詢 = 最佳”

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

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

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

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

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

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

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

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

誤區(qū)四:忽略 proxy_set_header

若后端 Java 應用需要獲取真實客戶端 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;:復用 TCP 連接,減少三次握手開銷,提升吞吐 15%~25%。

進階:Nginx 的其他負載均衡策略(了解即可)

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

1. 最少連接(least_conn)

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

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

2. 響應時間(fair)—— 需第三方模塊

根據(jù)后端響應時間動態(tài)分配,響應快的多分,響應慢的少分。

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

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

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

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

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

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

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

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

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

為了便于你本地快速復現(xiàn),這里提供一個 Docker Compose 腳本,一鍵啟動 3 個 Java 應用 + 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;
        }
    }
}

啟動命令

docker-compose up -d

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

結(jié)語:負載均衡不是終點,是起點

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

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

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

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

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

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

附錄:Nginx 負載均衡常用指令速查表

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

最后一句

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

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

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

相關(guān)文章

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

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

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

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

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

    Nginx 403 forbidden的解決辦法

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

    nginx部署到服務器后文件上傳提示405

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

    當Nginx所在服務器的磁盤空間滿時的影響以及如何避免這一問題

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

    centos6.5下Nginx簡單安裝教程

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

    nginx反向代理java項目方式

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

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

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

    Nginx的信號控制

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

    Nginx搭建負載均衡及常見問題處理

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

最新評論

宁化县| 南安市| 图木舒克市| 灵台县| 托克逊县| 古田县| 永修县| 广昌县| 彭山县| 大埔县| 山东省| 徐州市| 古田县| 东乡| 嘉峪关市| 彭山县| 章丘市| 鄂托克前旗| 黄陵县| 宝坻区| 北海市| 巴彦县| 晋城| 马尔康县| 吉安县| 武山县| 绍兴市| 曲靖市| 海安县| 九龙坡区| 满城县| 衡南县| 称多县| 砀山县| 攀枝花市| 永城市| 长武县| 金湖县| 湖南省| 横山县| 淮阳县|