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

Nginx反向代理之域名轉發(fā)與路徑重寫配置指南

 更新時間:2026年07月10日 08:44:48   作者:知遠漫談  
在現(xiàn)代互聯(lián)網(wǎng)架構中,反向代理早已不再是可選技能,而是構建高可用、高性能、安全穩(wěn)定服務的核心基石,本文將帶你深入 Nginx 反向代理的進階世界,系統(tǒng)性地解析域名轉發(fā)與路徑重寫兩大核心機制,需要的朋友可以參考下

引言

在現(xiàn)代互聯(lián)網(wǎng)架構中,反向代理早已不再是“可選技能”,而是構建高可用、高性能、安全穩(wěn)定服務的核心基石。Nginx 作為最流行的反向代理服務器之一,憑借其輕量、高效、模塊化的設計,成為無數(shù)企業(yè)級應用的首選。然而,許多開發(fā)者對 Nginx 的理解仍停留在“簡單轉發(fā)”層面——proxy_pass http://localhost:8080; 就是全部。殊不知,真正的力量在于精準控制流量的流向與形態(tài):如何根據(jù)域名動態(tài)路由?如何將 /api/v1/user 透明重寫為 /user-service/api/v1/user?如何在不修改后端代碼的前提下,實現(xiàn)多租戶、灰度發(fā)布、API 網(wǎng)關式管理?

本文將帶你深入 Nginx 反向代理的進階世界,系統(tǒng)性地解析域名轉發(fā)路徑重寫兩大核心機制。我們將從基礎語法講起,逐步過渡到復雜場景實戰(zhàn),結合真實 Java 后端服務示例,展示如何通過 Nginx 實現(xiàn)無侵入式架構升級。你將學會如何用幾行配置,讓一個原本只能訪問 http://app.example.com:8080 的 Spring Boot 服務,對外表現(xiàn)為 https://api.yourcompany.com/v1/users,同時還能自動處理負載均衡、SSL 終止、緩存策略和安全頭注入。

無論你是運維工程師、后端開發(fā)者,還是全棧架構師,掌握這些技能都將極大提升你對系統(tǒng)流量的掌控力。準備好了嗎?讓我們開啟這場從“能用”到“優(yōu)雅”的進階之旅

一、反向代理基礎:理解 Nginx 的流量入口

在深入域名轉發(fā)與路徑重寫之前,我們必須先厘清一個根本問題:Nginx 是如何“代理”請求的?

想象一下,你的用戶通過瀏覽器訪問 https://api.example.com/users。這個請求首先抵達的是 Nginx 服務器(監(jiān)聽 443 端口),而非你的 Java 應用(運行在 8080 端口)。Nginx 接收請求后,根據(jù)配置規(guī)則,決定“把這個問題交給誰處理”——可能是本地的 Tomcat,也可能是遠在 AWS 的微服務集群。這個“中間人”角色,就是反向代理的本質(zhì)。

1.1 最基礎的 proxy_pass 配置

server {
    listen 443 ssl;
    server_name api.example.com;
    ssl_certificate /etc/ssl/certs/api.example.com.crt;
    ssl_certificate_key /etc/ssl/private/api.example.com.key;
    location / {
        proxy_pass http://localhost:8080;
        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;
    }
}

這段配置看似簡單,實則暗藏玄機:

  • listen 443 ssl;:監(jiān)聽 HTTPS 請求
  • server_name api.example.com;:匹配請求頭中的 Host 字段,確保只有訪問該域名的請求才會被處理
  • location / { ... }:匹配所有路徑(根路徑)
  • proxy_pass http://localhost:8080;:將請求轉發(fā)到本地 8080 端口的 Java 服務

關鍵點proxy_pass 后面的 URL 是否包含路徑,決定了 Nginx 如何處理原始請求路徑!

1.2 路徑拼接陷阱:帶路徑 vs 不帶路徑

這是新手最容易踩的坑!

情況一:proxy_pass不帶路徑

location /api/ {
    proxy_pass http://backend:8080;  # 注意:沒有尾部 /
}

請求:https://api.example.com/api/v1/users
→ Nginx 轉發(fā)為:http://backend:8080/api/v1/users

行為:Nginx 將 location 匹配的部分(/api/原樣保留,拼接到目標 URL 后面。

情況二:proxy_pass帶路徑

location /api/ {
    proxy_pass http://backend:8080/service/;  # 注意:有尾部 /
}

請求:https://api.example.com/api/v1/users
→ Nginx 轉發(fā)為:http://backend:8080/service/v1/users

行為:Nginx 會移除 location 中匹配的路徑部分(/api/),然后將剩余部分(v1/users)拼接到 proxy_pass 的路徑之后(/service/)。

情況三:錯誤組合(不帶 / 的 location + 帶路徑的 proxy_pass)

location /api {  # 沒有尾部 /
    proxy_pass http://backend:8080/service/;  # 有尾部 /
}

請求:https://api.example.com/api/v1/users
→ Nginx 轉發(fā)為:http://backend:8080/service/v1/users ?(看似正常)

但請求:https://api.example.com/api(無尾部)
→ Nginx 轉發(fā)為:http://backend:8080/service ?

問題來了:如果后端服務期望 /api 作為路徑前綴,而你卻在 proxy_pass 中重寫了它,那么后端代碼中 @RequestMapping("/api") 的路徑將永遠無法匹配,因為請求到達時已經(jīng)變成了 /service。

最佳實踐

  • 如果 location/ 結尾 → proxy_pass 也以 / 結尾
  • 如果 location 不以 / 結尾 → proxy_pass 也不應帶路徑
  • 強烈建議:統(tǒng)一使用帶 / 的寫法,語義清晰,避免歧義

1.3 Java 后端如何感知真實請求?

Nginx 作為代理,會“隱藏”客戶端的真實 IP、協(xié)議、主機名。如果你的 Java 應用(如 Spring Boot)需要記錄訪問日志、做權限校驗、生成完整 URL,就必須依賴 Nginx 傳遞的頭部信息。

@RestController
@RequestMapping("/api/v1")
public class UserController {
    @GetMapping("/users")
    public ResponseEntity<String> getUsers(
            HttpServletRequest request) {
        String clientIp = request.getHeader("X-Real-IP");
        String forwardedHost = request.getHeader("Host");
        String scheme = request.getHeader("X-Forwarded-Proto");
        System.out.println("Client IP: " + clientIp);
        System.out.println("Original Host: " + forwardedHost);
        System.out.println("Protocol: " + scheme);
        return ResponseEntity.ok("Hello from Java backend!");
    }
}

對應的 Nginx 配置必須包含:

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;

為什么需要 X-Forwarded-For?
因為客戶端真實 IP 可能經(jīng)過多層代理(CDN、負載均衡器等),$proxy_add_x_forwarded_for 會追加每一層的 IP,形成鏈式記錄,如:192.168.1.10, 10.0.0.5, 172.16.0.1

實際項目中,Spring Boot 可通過 server.forward-headers-strategy=native + spring-boot-starter-web 自動識別這些頭,無需手動解析。但理解其原理,對排查問題至關重要。

二、域名轉發(fā):一個 Nginx 實例,服務多個業(yè)務域

現(xiàn)實世界中,很少有系統(tǒng)只服務一個域名。你可能有:

  • api.yourcompany.com → 提供 REST API
  • admin.yourcompany.com → 管理后臺
  • static.yourcompany.com → 靜態(tài)資源
  • legacy.yourcompany.com → 舊系統(tǒng)遷移中

Nginx 的 server 塊可以定義多個,每個 server_name 對應一個獨立的虛擬主機。這是實現(xiàn)多租戶、多服務統(tǒng)一入口的核心手段。

2.1 多域名基礎配置示例

# 1. API 服務
server {
    listen 443 ssl;
    server_name api.yourcompany.com;
    ssl_certificate /etc/ssl/certs/api.crt;
    ssl_certificate_key /etc/ssl/private/api.key;
    location / {
        proxy_pass http://api-backend:8080;
        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;
    }
}
# 2. 管理后臺
server {
    listen 443 ssl;
    server_name admin.yourcompany.com;
    ssl_certificate /etc/ssl/certs/admin.crt;
    ssl_certificate_key /etc/ssl/private/admin.key;
    location / {
        proxy_pass http://admin-backend:9090;
        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;
    }
}
# 3. 靜態(tài)資源(可緩存)
server {
    listen 443 ssl;
    server_name static.yourcompany.com;
    ssl_certificate /etc/ssl/certs/static.crt;
    ssl_certificate_key /etc/ssl/private/static.key;
    location / {
        root /var/www/static;
        add_header Cache-Control "public, max-age=31536000";
        add_header Access-Control-Allow-Origin "*";
    }
}

你可以在 https://httpbin.org/headers 測試你的請求頭是否正確傳遞。只需用瀏覽器訪問該鏈接,它會返回你發(fā)送的所有 HTTP 頭信息,包括 Host、X-Forwarded-* 等。

2.2 通配符域名與子域名泛解析

假設你的系統(tǒng)支持多租戶,每個租戶都有獨立子域名:

  • tenant1.yourcompany.com
  • tenant2.yourcompany.com
  • *.yourcompany.com

Nginx 支持正則表達式和通配符:

server {
    listen 443 ssl;
    server_name ~^(?<tenant>.+)\.yourcompany\.com$;
    ssl_certificate /etc/ssl/certs/wildcard.crt;
    ssl_certificate_key /etc/ssl/private/wildcard.key;
    # 從域名中提取租戶 ID,傳遞給后端
    set $tenant_id $tenant;
    location / {
        proxy_pass http://tenant-service:8080;
        proxy_set_header X-Tenant-ID $tenant_id;  # 自定義頭,后端可讀取
        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;
    }
}

在 Java 中,你可以這樣獲取租戶 ID:

@GetMapping("/dashboard")
public ResponseEntity<Map<String, Object>> getDashboard(
        HttpServletRequest request) {
    String tenantId = request.getHeader("X-Tenant-ID");
    if (tenantId == null || tenantId.isEmpty()) {
        return ResponseEntity.status(403).body(Map.of("error", "Tenant ID required"));
    }
    // 根據(jù) tenantId 查詢數(shù)據(jù)庫,返回租戶專屬數(shù)據(jù)
    DashboardData data = dashboardService.findByTenant(tenantId);
    return ResponseEntity.ok(data.toMap());
}

這種模式廣泛用于 SaaS 平臺,如 Notion、Airtable、Salesforce 的多租戶架構。無需為每個租戶部署獨立服務,一個后端實例即可處理所有子域名請求。

2.3 域名重定向:從 HTTP 到 HTTPS,從舊域到新域

你可能需要將舊域名遷移到新域名,或強制所有流量走 HTTPS:

# 強制 HTTP 跳轉到 HTTPS
server {
    listen 80;
    server_name api.yourcompany.com www.api.yourcompany.com;
    return 301 https://$host$request_uri;
}
# 舊域名重定向到新域名
server {
    listen 443 ssl;
    server_name legacy.yourcompany.com;
    ssl_certificate /etc/ssl/certs/legacy.crt;
    ssl_certificate_key /etc/ssl/private/legacy.key;
    location / {
        return 301 https://api.yourcompany.com$request_uri;
    }
}

return 301 是永久重定向,搜索引擎會更新索引,瀏覽器也會緩存該跳轉,提升 SEO 和用戶體驗。

三、路徑重寫:讓后端“看不見”前端路徑

路徑重寫(Rewrite)是 Nginx 最強大的功能之一。它允許你在請求被轉發(fā)前,動態(tài)修改請求的 URI,而用戶和瀏覽器對此完全無感知。

3.1 使用 rewrite 指令:基礎語法

rewrite regex replacement [flag];
  • regex:正則表達式,匹配請求路徑
  • replacement:替換后的路徑
  • flag:可選標志,如 last、break、redirect、permanent

示例 1:重寫/old-api/xxx→/new-api/xxx

location /old-api/ {
    rewrite ^/old-api/(.*)$ /new-api/$1 last;
    proxy_pass http://backend:8080;
}

請求:/old-api/v1/users/123
→ 被重寫為:/new-api/v1/users/123
→ 轉發(fā)到:http://backend:8080/new-api/v1/users/123

注意:rewrite 發(fā)生在 proxy_pass 之前!所以 proxy_pass 只需指向后端的根路徑即可。

示例 2:移除 URL 中的版本號(兼容舊客戶端)

location ~ ^/v[0-9]+/api/ {
    rewrite ^/v[0-9]+/(api/.*)$ /$1 last;
    proxy_pass http://backend:8080;
}

請求:/v1/api/users/api/users
請求:/v2/api/orders/api/orders

這個技巧在 API 版本遷移中極為實用。你可以在新版本中逐步淘汰 /v1/,而無需強制所有客戶端升級。

3.2 使用 location + proxy_pass 實現(xiàn)更優(yōu)雅的重寫

有時,rewrite 不是最佳選擇。更推薦使用 location 的正則匹配 + proxy_pass 帶路徑的組合。

location ~ ^/v[0-9]+/api/(.*)$ {
    proxy_pass http://backend:8080/api/$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;
}

這個寫法更清晰、更高效,因為:

  • Nginx 在 location 匹配階段就捕獲了路徑參數(shù)((.*)
  • proxy_pass 直接拼接,無需額外的 rewrite 指令
  • 避免了 rewrite 的額外處理開銷

性能對比:在高并發(fā)場景下,location + proxy_passrewrite 快 15%-20%,因為減少了正則引擎的二次匹配。

3.3 實戰(zhàn)案例:將前端 SPA 路由轉發(fā)到后端 API

假設你有一個 Vue.js 前端部署在 https://app.yourcompany.com,后端 API 部署在 https://api.yourcompany.com。但你希望用戶只記住一個域名:https://app.yourcompany.com

于是你這樣配置:

server {
    listen 443 ssl;
    server_name app.yourcompany.com;
    ssl_certificate /etc/ssl/certs/app.crt;
    ssl_certificate_key /etc/ssl/private/app.key;
    # 靜態(tài)資源:前端打包文件
    location / {
        root /var/www/frontend;
        try_files $uri $uri/ /index.html;
    }
    # API 路徑重寫:所有 /api/* 轉發(fā)到后端
    location /api/ {
        proxy_pass http://backend:8080/;
        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;
    }
}

前端代碼中,你只需寫:

// Vue.js / React 請求
axios.get('/api/users'); // 實際請求的是 https://app.yourcompany.com/api/users
// 但 Nginx 會把它轉成 http://backend:8080/api/users

無需跨域配置!無需 CORS!前端和后端“看起來”在同一個域下,完美解決同源策略問題!

3.4 復雜路徑重寫:多級路徑映射

想象一個復雜的微服務架構:

用戶請求路徑實際后端服務說明
/v1/user/profileuser-service:8080/api/v1/profile用戶服務
/v1/order/listorder-service:8080/api/v1/orders訂單服務
/v1/payment/notifypayment-service:8080/webhook/v1/notify支付回調(diào)

你可以用多個 location 實現(xiàn)精準路由:

server {
    listen 443 ssl;
    server_name api.yourcompany.com;
    ssl_certificate /etc/ssl/certs/api.crt;
    ssl_certificate_key /etc/ssl/private/api.key;
    # 用戶服務
    location ~ ^/v1/user/(.*)$ {
        proxy_pass http://user-service:8080/api/v1/$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;
    }
    # 訂單服務
    location ~ ^/v1/order/(.*)$ {
        proxy_pass http://order-service:8080/api/v1/$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;
    }
    # 支付服務(特殊路徑)
    location ~ ^/v1/payment/notify$ {
        proxy_pass http://payment-service:8080/webhook/v1/notify;
        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;
    }
    # 默認兜底:404
    location / {
        return 404;
    }
}

每個服務都有獨立的路徑空間,互不干擾,易于維護。后端服務無需關心“全局路徑前綴”,只專注自己的業(yè)務路徑。

四、高級技巧:條件路由、負載均衡與動態(tài)代理

Nginx 的強大遠不止靜態(tài)配置。它支持基于請求頭、Cookie、IP、變量的條件判斷,實現(xiàn)智能路由。

4.1 基于 User-Agent 的路由(移動端 vs PC)

map $http_user_agent $backend {
    default "mobile-backend";
    ~*"(Chrome|Firefox|Safari|Edge)" "web-backend";
}
server {
    listen 443 ssl;
    server_name app.yourcompany.com;
    location / {
        proxy_pass http://$backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}
  • 如果 User-Agent 包含 Chrome/Firefox → 轉發(fā)到 web-backend
  • 否則(如手機瀏覽器)→ 轉發(fā)到 mobile-backend

你可以為移動端部署輕量版 API,減少 JSON 字段、關閉日志、啟用壓縮,提升體驗。

4.2 基于 Cookie 的灰度發(fā)布(A/B 測試)

假設你正在發(fā)布新版本的用戶服務,想讓 10% 的用戶訪問新版。

map $cookie_gateway_version $upstream {
    default "backend-v1";
    "v2" "backend-v2";
}
server {
    listen 443 ssl;
    server_name api.yourcompany.com;
    location /api/v1/user {
        proxy_pass http://$upstream/api/v1/user;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

然后在前端代碼中,隨機設置 Cookie:

// 在用戶登錄后隨機設置
if (Math.random() < 0.1) {
    document.cookie = "gateway_version=v2; path=/; max-age=3600";
}

這種方式無需修改 Nginx 配置,僅通過前端控制 Cookie,即可實現(xiàn)無感知灰度發(fā)布。適用于金融、電商等高敏感場景。

4.3 負載均衡:多實例自動分發(fā)

upstream user-service {
    server 10.0.0.10:8080 weight=3;
    server 10.0.0.11:8080 weight=1;
    server 10.0.0.12:8080 backup;  # 備用節(jié)點
}
server {
    listen 443 ssl;
    server_name api.yourcompany.com;
    location /api/v1/user {
        proxy_pass http://user-service;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
  • weight=3:每 4 個請求,3 個發(fā)給 10.0.0.10,1 個發(fā)給 10.0.0.11
  • backup:只有當主節(jié)點全掛時才啟用

?? Nginx 支持多種負載均衡算法:round-robin(默認)、least_conn(最少連接)、ip_hash(會話保持)

upstream user-service {
    ip_hash;  # 同一 IP 的請求總是發(fā)給同一臺后端
    server 10.0.0.10:8080;
    server 10.0.0.11:8080;
}

ip_hash 適用于需要會話保持的場景(如購物車、登錄態(tài)),但犧牲了負載均衡的均勻性。

4.4 動態(tài)上游:結合 Lua 或外部服務(進階)

雖然 Nginx 本身不支持動態(tài) DNS 查詢,但可通過 ngx_http_lua_module 實現(xiàn):

location /dynamic-api {
    content_by_lua_block {
        local res = ngx.location.capture("/resolve-backend")
        local backend = res.body
        ngx.req.set_uri("/api/v1/user", false)
        ngx.var.upstream = backend
        ngx.exec("/proxy-to-backend")
    }
}

這需要 OpenResty 環(huán)境,適合高階用戶。普通場景建議使用 Consul + nginx-upsync-module 實現(xiàn)動態(tài)上游更新。

五、Java 后端實戰(zhàn):如何配合 Nginx 構建現(xiàn)代化網(wǎng)關

現(xiàn)在,我們來構建一個完整的 Java 微服務 + Nginx 反向代理系統(tǒng)。

5.1 后端服務:Spring Boot API

package com.example.gatewaydemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
@SpringBootApplication
@RestController
public class GatewayDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayDemoApplication.class, args);
    }
    @GetMapping("/api/v1/user")
    public Map<String, Object> getUserInfo(
            HttpServletRequest request,
            @RequestHeader(value = "X-Tenant-ID", required = false) String tenantId) {
        Map<String, Object> response = new HashMap<>();
        response.put("status", "success");
        response.put("message", "Hello from Java backend!");
        response.put("requestedPath", request.getRequestURI());
        response.put("clientIp", request.getHeader("X-Real-IP"));
        response.put("originalHost", request.getHeader("Host"));
        response.put("tenantId", tenantId);
        response.put("protocol", request.getHeader("X-Forwarded-Proto"));
        return response;
    }
    @GetMapping("/api/v1/health")
    public Map<String, String> health() {
        Map<String, String> health = new HashMap<>();
        health.put("status", "UP");
        health.put("version", "1.2.3");
        return health;
    }
}

啟動后,訪問 http://localhost:8080/api/v1/user,你會看到:

{
  "status": "success",
  "message": "Hello from Java backend!",
  "requestedPath": "/api/v1/user",
  "clientIp": "127.0.0.1",
  "originalHost": "localhost:8080",
  "tenantId": null,
  "protocol": "http"
}

5.2 Nginx 配置:統(tǒng)一入口 + 路徑重寫 + 多域名

# 定義上游組
upstream java-backend {
    server 127.0.0.1:8080;
}
server {
    listen 443 ssl;
    server_name api.example.com www.api.example.com;
    ssl_certificate /etc/ssl/certs/api.crt;
    ssl_certificate_key /etc/ssl/private/api.key;
    # 所有 /api/v1/* 請求轉發(fā)到后端
    location ~ ^/api/v1/(.*)$ {
        proxy_pass http://java-backend/api/v1/$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;
        # 添加安全頭
        add_header X-Content-Type-Options nosniff;
        add_header X-Frame-Options DENY;
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    }
    # 健康檢查端點(不經(jīng)過重寫)
    location /health {
        proxy_pass http://java-backend/health;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
    # 默認響應
    location / {
        return 404 "Not Found. Use /api/v1/* endpoints.";
    }
}
# 管理后臺
server {
    listen 443 ssl;
    server_name admin.example.com;
    ssl_certificate /etc/ssl/certs/admin.crt;
    ssl_certificate_key /etc/ssl/private/admin.key;
    location / {
        proxy_pass http://java-backend;
        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;
    }
}
# 強制 HTTPS
server {
    listen 80;
    server_name api.example.com www.api.example.com admin.example.com;
    return 301 https://$host$request_uri;
}

5.3 測試驗證

  1. 啟動 Java 服務:java -jar gateway-demo.jar
  2. 訪問:https://api.example.com/api/v1/user

你會看到響應:

{
  "status": "success",
  "message": "Hello from Java backend!",
  "requestedPath": "/api/v1/user",
  "clientIp": "192.168.1.100",
  "originalHost": "api.example.com",
  "tenantId": null,
  "protocol": "https"
}

? 注意:originalHostapi.example.com,而非 localhost:8080,說明 Nginx 成功傳遞了原始域名。

  1. 訪問:https://admin.example.com/api/v1/user

你會看到:404 —— 因為后端服務沒有 /api/v1/user 路徑(它只在 api.example.com 下暴露)

這正是我們想要的:不同域名暴露不同 API,實現(xiàn)邏輯隔離!

六、性能優(yōu)化與安全加固:生產(chǎn)環(huán)境必看

6.1 緩存靜態(tài)內(nèi)容

location ~* \.(jpg|jpeg|png|gif|ico|css|js|json|woff|woff2)$ {
    root /var/www/static;
    expires 1y;
    add_header Cache-Control "public, immutable";
    add_header Access-Control-Allow-Origin "*";
}

減少后端壓力,提升前端加載速度。

6.2 限制請求速率(防刷)

limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
server {
    location /api/v1/user {
        limit_req zone=api_limit burst=20 nodelay;
        proxy_pass http://java-backend;
        ...
    }
}
  • 每秒最多 10 個請求
  • 允許突發(fā) 20 個(burst)
  • nodelay:不延遲,直接拒絕超出部分

6.3 防止惡意請求頭

if ($http_user_agent ~* "sqlmap|nmap|nikto") {
    return 403;
}
if ($http_referer ~* "(spam|porn|gambling)") {
    return 403;
}

可結合 nginx-module-vtsModSecurity 做更深度的 WAF 防護。

6.4 啟用 Gzip 壓縮

gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

通??蓽p少 70% 的響應體積,尤其對 JSON API 效果顯著。

七、故障排查與日志分析

7.1 查看 Nginx 配置是否正確

nginx -t

輸出 syntax is oktest is successful 才能重啟。

7.2 實時查看訪問日志

tail -f /var/log/nginx/access.log

典型日志格式:

192.168.1.10 - - [15/Apr/2024:10:23:45 +0800] "GET /api/v1/user HTTP/1.1" 200 1234 "-" "Mozilla/5.0"

7.3 自定義日志格式(記錄更多上下文)

log_format detailed '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent" '
                    'rt=$request_time uct="$upstream_connect_time" '
                    'uht="$upstream_header_time" urt="$upstream_response_time" '
                    'host="$host" x-forwarded-for="$http_x_forwarded_for"';
access_log /var/log/nginx/access.log detailed;

日志中將包含:

  • 請求耗時(request_time
  • 上游連接時間(upstream_connect_time
  • 上游響應頭時間(upstream_header_time
  • 上游響應體時間(upstream_response_time

一旦后端慢,你就能立即判斷是網(wǎng)絡問題、后端處理慢,還是數(shù)據(jù)庫慢!

八、架構演進:從 Nginx 到服務網(wǎng)格

隨著微服務規(guī)模擴大,Nginx 的配置會變得復雜難維護。此時,你可以考慮:

方案適用場景優(yōu)勢劣勢
Nginx小中型系統(tǒng),單一入口配置簡單、性能極高、資源消耗低無服務發(fā)現(xiàn)、無熔斷、無追蹤
Spring Cloud GatewayJava 技術棧統(tǒng)一深度集成 Spring 生態(tài)、支持斷路器、重試JVM 開銷大、不適合靜態(tài)資源
Envoy / Istio大型云原生系統(tǒng)服務網(wǎng)格、mTLS、流量鏡像、金絲雀發(fā)布學習曲線陡峭、運維復雜

建議路徑
小團隊 → Nginx 精細化配置
中型團隊 → Nginx + Prometheus + Grafana 監(jiān)控
大型團隊 → Istio + K8s + Linkerd

九、總結:你掌握的,不只是配置,是架構話語權

通過本文,你已經(jīng)掌握了:

? Nginx 反向代理的核心原理
? 域名轉發(fā)的多租戶實現(xiàn)
? 路徑重寫的四種優(yōu)雅寫法
? Java 后端如何感知真實請求
? 負載均衡、灰度發(fā)布、限流、安全頭
? 生產(chǎn)環(huán)境最佳實踐與故障排查

更重要的是,你理解了:

Nginx 不是“轉發(fā)工具”,它是你的“流量指揮官”。
它讓你能在不改動一行后端代碼的前提下,完成:

  • 多域名隔離
  • API 版本平滑遷移
  • 租戶路由
  • 灰度發(fā)布
  • 安全加固
  • 性能優(yōu)化

這,就是架構師的底氣。

十、延伸思考:如果你是 CTO,你會怎么設計?

想象你負責一個年交易額 10 億的電商平臺,有:

  • 10 個微服務(用戶、商品、訂單、支付、庫存、推薦、風控、物流、通知、后臺)
  • 3 個前端(Web、App、小程序)
  • 5 個地域數(shù)據(jù)中心
  • 每天 5000 萬次 API 調(diào)用

你會如何設計 Nginx 層?

建議架構:

[全球用戶]
     ↓
[CDN 緩存靜態(tài)資源]
     ↓
[邊緣 Nginx(全球 10 節(jié)點)]
     ↓
[區(qū)域 Nginx(北京/上海/廣州)]
     ↓
[服務網(wǎng)關(Spring Cloud Gateway)]
     ↓
[微服務集群(K8s)]
  • CDN:緩存圖片、CSS、JS
  • 邊緣 Nginx:做 DDOS 防護、IP 黑名單、SSL 終止
  • 區(qū)域 Nginx:做地域路由(如華北用戶走華北機房)
  • 網(wǎng)關:做鑒權、限流、日志、熔斷
  • 微服務:專注業(yè)務邏輯

Nginx 在這里,是流量的過濾器、加速器、調(diào)度器,不是簡單的代理。

結語:讓配置成為藝術

配置文件不是冰冷的文本,它是你系統(tǒng)架構的藍圖,是你與流量對話的語言。

當你能用一行 proxy_pass,讓千萬用戶無感知地切換后端服務;
當你能用一個 rewrite,讓舊系統(tǒng)優(yōu)雅退場;
當你能用一個 map,讓 A/B 測試毫秒級生效——

你,就不再是“寫代碼的人”,而是系統(tǒng)架構的設計師。

Nginx 的力量,不在于它能做什么,而在于它讓你不用做什么
你無需改 Java 代碼,無需重啟服務,無需發(fā)布新版本,就能完成一次全局流量重構。

這就是反向代理的終極魅力。

附錄:常用 Nginx 指令速查表

指令用途
proxy_pass轉發(fā)請求到后端
proxy_set_header設置轉發(fā)頭
rewrite重寫 URI
location匹配請求路徑
upstream定義后端集群
limit_req限流
gzip啟用壓縮
expires設置緩存
return返回 HTTP 狀態(tài)碼
map變量映射(強大!)
try_files優(yōu)先查找本地文件

以上就是Nginx反向代理之域名轉發(fā)與路徑重寫配置指南的詳細內(nèi)容,更多關于Nginx域名轉發(fā)與路徑重寫配置的資料請關注腳本之家其它相關文章!

相關文章

  • 使用LDAP實現(xiàn)Nginx用戶認證的示例

    使用LDAP實現(xiàn)Nginx用戶認證的示例

    本文主要使用Nginx和LDAP實現(xiàn)用戶認證,通過配置Nginx和安裝nginx-auth-ldap模塊,可以實現(xiàn)基于LDAP的認證邏輯,下面就來介紹一下,感興趣的可以了解一下
    2024-12-12
  • 前端項目中Nginx配置指南詳解

    前端項目中Nginx配置指南詳解

    這篇文章主要為大家詳細介紹了在前端項目開發(fā)中如何配置Nginx,文中的示例代碼講解詳細,具有一定的學習價值,感興趣的小伙伴可以了解一下
    2023-09-09
  • Linux下Nginx安裝教程

    Linux下Nginx安裝教程

    這篇文章主要為大家詳細介紹了Linux中Nginx的安裝教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • Forever+nginx部署Node站點的方法示例

    Forever+nginx部署Node站點的方法示例

    這篇文章主要介紹了Forever+nginx部署Node站點的方法示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-04-04
  • nginx+lua+redis 灰度發(fā)布實現(xiàn)方案

    nginx+lua+redis 灰度發(fā)布實現(xiàn)方案

    在微服務化進程中,利用nginx+lua+redis實現(xiàn)灰度發(fā)布至關重要,,通過nginx+lua反向代理,根據(jù)客戶端ip進行路由控制,配合redis存儲允許訪問微服務的ip地址,可以有效地進行用戶分流,感興趣的可以了解一下
    2024-10-10
  • Nginx 上傳大文件超時解決辦法

    Nginx 上傳大文件超時解決辦法

    這篇文章主要介紹了Nginx 上傳大文件超時解決辦法的相關資料,這里上傳文件并設置nginx的配置文件防止超時的情況,需要的朋友可以參考下
    2017-07-07
  • 通過配置nginx訪問服務器靜態(tài)資源的過程

    通過配置nginx訪問服務器靜態(tài)資源的過程

    文章介紹了圖片存儲路徑設置、Nginx服務器配置及通過http://192.168.206.170:8007/a.png訪問圖片的方法,涵蓋圖片管理與服務部署的核心步驟
    2025-08-08
  • nginx封空user_agent實現(xiàn)封禁迅雷的方法

    nginx封空user_agent實現(xiàn)封禁迅雷的方法

    nginx封空user_agent實現(xiàn)封禁迅雷的方法,需要的朋友可以參考下。
    2010-11-11
  • nginx訪問控制的實現(xiàn)示例

    nginx訪問控制的實現(xiàn)示例

    這篇文章主要介紹了nginx訪問控制的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-11-11
  • nginx處理http請求實例詳解

    nginx處理http請求實例詳解

    這篇文章主要介紹了nginx處理http請求實例詳解的相關資料,需要的朋友可以參考下
    2017-06-06

最新評論

南平市| 中方县| 高清| 昆明市| 烟台市| 秦安县| 微山县| 万源市| 屏东市| 凤翔县| 手游| 江华| 克拉玛依市| 普安县| 泸定县| 靖远县| 阳高县| 敦煌市| 文山县| 贵定县| 大埔县| 黎川县| 涞水县| 密山市| 津南区| 平凉市| 福安市| 安庆市| 温泉县| 定日县| 巴彦淖尔市| 铜陵市| 金堂县| 繁昌县| 富源县| 会昌县| 陇川县| 鄂托克旗| 叶城县| 延寿县| 怀集县|