1. 反向代理的概念
1.1. 什麼是反向代理?
反向代理是位於客戶端與後端伺服器之間的伺服器,負責接收客戶端的請求,將其轉發給後端伺服器,再將回應回傳給客戶端。
差異說明:
正向代理(客戶端側): Client → Forward Proxy → Internet → Server (隱藏客戶端)
反向代理(伺服器側): Client → Reverse Proxy → Backend Server (隱藏伺服器)
示意圖:
┌─────────┐ ┌──────────────┐ ┌──────────────┐
│ │ │ │ │ │
│ Client │────────▶│ Nginx │────────▶│ Backend │
│ │ │ Reverse Proxy│ │ Server │
│ │◀────────│ │◀────────│ │
└─────────┘ └──────────────┘ └──────────────┘
1.2. 為何使用反向代理?
1. 負載均衡:
- 將流量分散到多個後端伺服器
- 提升處理能力與可靠性
2. SSL/TLS 終止:
- Nginx 處理 SSL 加密/解密
- 後端伺服器無需處理 HTTPS
3. 快取:
- 快取靜態內容與 API 回應
- 降低後端伺服器負載
4. 安全性:
- 隱藏後端伺服器基礎架構
- 保護層(速率限制、防火牆)
- 集中式驗證
5. 壓縮:
- 對回應進行 Gzip 壓縮
- 減少頻寬使用量
6. 靜態檔案服務:
- Nginx 直接提供靜態檔案
- 後端僅處理動態內容
7. 多個後端:
- 將請求路由到不同應用程式
- 微服務架構
1.3. 常見應用場景
1. 單頁應用程式(SPA): / → React/Vue/Angular app /api/* → 後端 API 伺服器
微服務: /users/* → 使用者服務 /orders/* → 訂單服務 /payments/* → 付款服務
多個應用程式: site.com → 主網站 blog.site.com → WordPress 部落格 api.site.com → API 伺服器
舊版 + 新版: /old/* → 舊版 PHP 應用程式 /new/* → 新版 Node.js 應用程式
2. 基本 proxy_pass 設定
2.1. proxy_pass 語法
location /path/ {
proxy_pass http://backend_server;
}
簡單範例:
server { listen 80; server_name example.com;
location / { # 將所有請求轉發到後端 proxy_pass http://localhost:3000; } }
2.2. proxy_pass 與 URI
方式1:無尾部斜線
location /api { proxy_pass http://localhost:3000; }請求:/api/users
代理至:http://localhost:3000/api/users
(保留 /api 前綴)
方式2:有尾部斜線
location /api/ { proxy_pass http://localhost:3000/; }請求:/api/users
代理至:http://localhost:3000/users
(移除 /api 前綴)
方式3:指定特定路徑
location /api/ { proxy_pass http://localhost:3000/v1/; }請求:/api/users
代理至:http://localhost:3000/v1/users
(以 /v1 取代 /api)
詳細範例:
server { listen 80; server_name example.com;# 代理根路徑 location / { proxy_pass http://localhost:3000; } # 代理 API(移除 /api 前綴) location /api/ { proxy_pass http://localhost:4000/; } # 代理 admin(保留 /admin 前綴) location /admin { proxy_pass http://localhost:5000; } # 精確比對代理 location = /health { proxy_pass http://localhost:3000/healthcheck; }
}
2.3. 多後端代理
server { listen 80; server_name example.com;# 前端 SPA location / { root /var/www/html; try_files $uri $uri/ /index.html; } # API 後端 location /api/ { proxy_pass http://localhost:3000/; } # 驗證服務 location /auth/ { proxy_pass http://localhost:4000/; } # WebSocket 伺服器 location /ws/ { proxy_pass http://localhost:5000/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } # 靜態資源(CDN) location /static/ { proxy_pass http://cdn.example.com/; }
}
2.4. 使用變數的代理
server { listen 80; server_name example.com;# 根據子網域代理 location / { proxy_pass http://$http_host$request_uri; } # 使用自訂變數的代理 set $backend "localhost:3000"; location /api/ { proxy_pass http://$backend/; } # 條件代理 location /dynamic/ { if ($arg_version = "v2") { proxy_pass http://localhost:4000/; } proxy_pass http://localhost:3000/; }
}
2.5. 代理逾時設定
location /api/ { proxy_pass http://localhost:3000/;# 逾時設定 proxy_connect_timeout 60s; # 連線到上游的逾時 proxy_send_timeout 60s; # 發送請求的逾時 proxy_read_timeout 60s; # 讀取回應的逾時 # 緩衝區設定 proxy_buffering on; proxy_buffer_size 4k; proxy_buffers 8 4k; proxy_busy_buffers_size 8k;
}
3. 代理標頭
標頭對於讓後端伺服器了解原始請求資訊非常重要。
3.1. 必要的代理標頭
location / { proxy_pass http://localhost:3000;# Host 標頭 proxy_set_header Host $host; # 客戶端真實 IP proxy_set_header X-Real-IP $remote_addr; # 代理鏈 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 協定(http/https) proxy_set_header X-Forwarded-Proto $scheme; # 原始主機 proxy_set_header X-Forwarded-Host $host; # 連接埠 proxy_set_header X-Forwarded-Port $server_port;
}
3.2. 標頭說明
Host:
proxy_set_header Host $host;$host = 請求中的網域名稱
範例:example.com
後端收到:Host: example.com
X-Real-IP:
proxy_set_header X-Real-IP $remote_addr;$remote_addr = 直接連線到 Nginx 的客戶端 IP
範例:192.168.1.100
後端收到:X-Real-IP: 192.168.1.100
X-Forwarded-For:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;將客戶端 IP 附加到現有的 X-Forwarded-For 標頭
範例:
請求1:Client → Nginx → Backend
X-Forwarded-For: 192.168.1.100
請求2:Client → CDN → Nginx → Backend
X-Forwarded-For: 192.168.1.100, 10.0.0.50
$proxy_add_x_forwarded_for 保留代理鏈
X-Forwarded-Proto:
proxy_set_header X-Forwarded-Proto $scheme;$scheme = http 或 https
後端可知道原始請求是 HTTP 還是 HTTPS
對重新導向邏輯很重要
3.3. 完整標頭設定
http { # 定義標頭範本 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; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Port $server_port;server { listen 80; server_name example.com; location / { proxy_pass http://localhost:3000; # 繼承 http context 的標頭 } }
}
3.4. 自訂標頭
location /api/ { proxy_pass http://localhost:3000/;# 標準標頭 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; # 自訂標頭 proxy_set_header X-Request-ID $request_id; proxy_set_header X-Server-Name $hostname; proxy_set_header X-Forwarded-User $remote_user; # 移除標頭 proxy_set_header Authorization ""; # 移除驗證標頭 # 新增自訂值 proxy_set_header X-API-Version "v1"; proxy_set_header X-Environment "production";
}
3.5. WebSocket 標頭
location /ws/ { proxy_pass http://localhost:3000/;# WebSocket 專用標頭 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; # 標準標頭 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # WebSocket 逾時 proxy_read_timeout 3600s; proxy_send_timeout 3600s;
}
3.6. 保留原始標頭
location / { proxy_pass http://localhost:3000;# 傳遞所有原始標頭 proxy_pass_request_headers on; # 特定標頭 proxy_set_header Accept-Encoding $http_accept_encoding; proxy_set_header Accept-Language $http_accept_language; proxy_set_header Cookie $http_cookie; proxy_set_header Referer $http_referer; proxy_set_header User-Agent $http_user_agent;
}
3.7. 安全標頭
location / { proxy_pass http://localhost:3000;# 標準代理標頭 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 隱藏 Nginx 版本 proxy_hide_header X-Powered-By; proxy_hide_header Server; # 新增安全標頭 add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always; add_header Referrer-Policy "no-referrer-when-downgrade" always;
}
4. 上游伺服器與負載均衡
4.1. 基本 Upstream 區塊
# 定義 upstream upstream backend { server localhost:3000; server localhost:3001; server localhost:3002; }server { listen 80; server_name example.com;
location / { proxy_pass http://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; }
}
4.2. 負載均衡方法
1. 輪詢(預設):
upstream backend { # 輪詢:依序分配給每台伺服器 server localhost:3000; server localhost:3001; server localhost:3002; }請求1 → 3000
請求2 → 3001
請求3 → 3002
請求4 → 3000(循環)
2. 最少連線:
upstream backend { least_conn; # 連線數最少的伺服器server localhost:3000; server localhost:3001; server localhost:3002;}
適合長連線
均勻分散負載
3. IP 雜湊(黏性會話):
upstream backend { ip_hash; # 相同客戶端 → 相同伺服器server localhost:3000; server localhost:3001; server localhost:3002;}
客戶端 192.168.1.100 → 始終路由到伺服器 3000
客戶端 192.168.1.101 → 始終路由到伺服器 3001
適合基於 Session 的應用程式
4. 通用雜湊:
upstream backend { hash $request_uri consistent; # 按 URI 雜湊server localhost:3000; server localhost:3001; server localhost:3002;}
相同 URI → 相同伺服器
適合快取
5. 隨機:
upstream backend { random; # 隨機選擇伺服器server localhost:3000; server localhost:3001; server localhost:3002;
}
4.3. 伺服器權重
upstream backend { # 權重較高的伺服器接收更多請求 server localhost:3000 weight=3; # 60% 流量 server localhost:3001 weight=1; # 20% 流量 server localhost:3002 weight=1; # 20% 流量 }總權重 = 5
伺服器 3000:3/5 = 60%
伺服器 3001:1/5 = 20%
伺服器 3002:1/5 = 20%
權重使用場景:
upstream backend { # 正式環境伺服器 server prod1.example.com weight=5; server prod2.example.com weight=5;# 金絲雀部署 - 10% 流量 server canary.example.com weight=1;
}
4.4. 備援伺服器
upstream backend { server localhost:3000; server localhost:3001; server localhost:3002 backup; # 僅在主要伺服器故障時使用 }3002 只有在 3000 和 3001 都無法使用時才接收流量
4.5. 伺服器參數
upstream backend { server localhost:3000 weight=5 max_fails=3 fail_timeout=30s; server localhost:3001 weight=5 max_fails=3 fail_timeout=30s; server localhost:3002 backup; server localhost:3003 down; # 暫時停用 }參數說明:
weight=N - 權重(預設 1)
max_fails=N - 標記為故障前的失敗次數(預設 1)
fail_timeout=T - 逾時持續時間(預設 10s)
backup - 備援伺服器
down - 暫時停用
4.6. 進階 Upstream 設定
upstream backend { least_conn; # 負載均衡方法# 伺服器設定 server srv1.example.com:8080 weight=3 max_fails=2 fail_timeout=30s; server srv2.example.com:8080 weight=3 max_fails=2 fail_timeout=30s; server srv3.example.com:8080 weight=2 max_fails=2 fail_timeout=30s; server srv4.example.com:8080 backup; # 保持連線 keepalive 32; # 保持 32 個閒置連線到上游 keepalive_timeout 60s; keepalive_requests 100;}
server { listen 80;
location / { proxy_pass http://backend; # 保持連線所需的 HTTP 版本 proxy_http_version 1.1; proxy_set_header Connection ""; # 標準標頭 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
}
4.7. 多個 Upstream
# API 後端 upstream api_backend { least_conn; server api1.example.com:3000; server api2.example.com:3000; server api3.example.com:3000; }驗證服務
upstream auth_backend { server auth1.example.com:4000; server auth2.example.com:4000; }
WebSocket 服務
upstream websocket_backend { ip_hash; # WebSocket 的黏性會話 server ws1.example.com:5000; server ws2.example.com:5000; }
server { listen 80; server_name example.com;
location /api/ { proxy_pass http://api_backend/; } location /auth/ { proxy_pass http://auth_backend/; } location /ws/ { proxy_pass http://websocket_backend/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; }
}
5. 基本健康檢查
5.1. 被動健康檢查
Nginx 根據伺服器的回應自動偵測故障的伺服器。
upstream backend { server localhost:3000 max_fails=3 fail_timeout=30s; server localhost:3001 max_fails=3 fail_timeout=30s; server localhost:3002 max_fails=3 fail_timeout=30s; }max_fails=3:連續失敗 3 次後
fail_timeout=30s:伺服器標記為停機 30 秒
30 秒後,Nginx 重試該伺服器
運作方式:
1. 請求發送到 localhost:3000
2. 伺服器返回 502、503、504 或逾時 → 失敗次數 = 1
3. 下一個請求傳到 3000
4. 伺服器再次失敗 → 失敗次數 = 2
5. 下一個請求傳到 3000
6. 伺服器第三次失敗 → 失敗次數 = 3 → 伺服器標記為停機
7. 流量路由到 3001 和 3002
8. 30 秒後,Nginx 重試 3000
9. 若 3000 正常回應 → 失敗次數重置,伺服器上線
5.2. 主動健康檢查(Nginx Plus)
Nginx Plus 支援主動健康檢查(開源版本不支援)。
# 僅 Nginx Plus upstream backend { zone backend 64k; server localhost:3000; server localhost:3001; server localhost:3002; }server { listen 80;
location / { proxy_pass http://backend; health_check interval=5s fails=3 passes=2 uri=/health; }}
interval=5s:每 5 秒檢查一次
fails=3:失敗 3 次後標記為停機
passes=2:成功 2 次後標記為上線
uri=/health:要檢查的端點
5.3. 自訂健康檢查端點
後端實作(Node.js 範例):
// health.js const express = require('express'); const app = express();app.get('/health', (req, res) => { // 檢查資料庫連線 // 檢查相依服務 // 檢查記憶體使用量等
const health = { status: 'ok', timestamp: new Date().toISOString(), uptime: process.uptime(), memory: process.memoryUsage() }; res.status(200).json(health);});
app.listen(3000);
Nginx 設定:
upstream backend { server localhost:3000 max_fails=3 fail_timeout=30s; server localhost:3001 max_fails=3 fail_timeout=30s; }server { listen 80;
location / { proxy_pass http://backend; } # 健康檢查端點(非公開) location /health { access_log off; proxy_pass http://backend; # 僅允許本機存取 allow 127.0.0.1; deny all; }
}
5.4. 外部健康檢查
使用外部腳本監控並更新上游設定。
監控腳本:
#!/bin/bashhealth_check.sh
UPSTREAM_SERVERS=( "localhost:3000" "localhost:3001" "localhost:3002" )
HEALTH_ENDPOINT="/health"
for server in "${UPSTREAM_SERVERS[@]}"; do response=$(curl -s -o /dev/null -w "%{http_code}" "http://$server$HEALTH_ENDPOINT")
if [ "$response" = "200" ]; then echo "$(date) - $server 正常" else echo "$(date) - $server 停機(HTTP $response)" # 發送警報 # 更新 upstream 設定 # 重新載入 Nginx fi
done
Crontab:
# 每分鐘執行健康檢查
- /usr/local/bin/health_check.sh >> /var/log/health_check.log 2>&1
5.5. 使用 Stub Status 監控
server {
listen 8080;
server_name localhost;
location /nginx_status {
stub_status;
access_log off;
allow 127.0.0.1;
deny all;
}
}
查看狀態:
curl http://localhost:8080/nginx_status
輸出:
Active connections: 291
server accepts handled requests
16630948 16630948 31070465
Reading: 6 Writing: 179 Waiting: 106
5.6. 使用腳本進行健康檢查
Python 健康檢查:
#!/usr/bin/env python3
health_monitor.py
import requests
import time
import smtplib
from email.message import EmailMessage
BACKENDS = [
'http://localhost:3000/health',
'http://localhost:3001/health',
'http://localhost:3002/health',
]
def check_health(url):
try:
response = requests.get(url, timeout=5)
return response.status_code == 200
except:
return False
def send_alert(backend, status):
msg = EmailMessage()
msg['Subject'] = f'後端警報:{backend}'
msg['From'] = '[email protected]'
msg['To'] = '[email protected]'
msg.set_content(f'後端 {backend} 狀態:{status}')
with smtplib.SMTP('localhost') as s:
s.send_message(msg)
def main():
while True:
for backend in BACKENDS:
if not check_health(backend):
print(f'{backend} 停機')
send_alert(backend, '停機')
else:
print(f'{backend} 正常')
time.sleep(60) # 每分鐘檢查一次
if name == 'main':
main()
6. 實際應用範例
6.1. Node.js 應用程式
後端(app.js):
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.json({
message: 'Hello from Node.js',
server: localhost:${PORT},
headers: req.headers
});
});
app.get('/api/users', (req, res) => {
res.json([
{ id: 1, name: 'User 1' },
{ id: 2, name: 'User 2' }
]);
});
app.get('/health', (req, res) => {
res.status(200).json({ status: 'ok' });
});
app.listen(PORT, () => {
console.log(Server running on port ${PORT});
});
Nginx 設定:
upstream nodejs_backend {
least_conn;
server localhost:3000 max_fails=3 fail_timeout=30s;
server localhost:3001 max_fails=3 fail_timeout=30s;
server localhost:3002 max_fails=3 fail_timeout=30s;
keepalive 32;
}
server {
listen 80;
server_name api.example.com;
access_log /var/log/nginx/nodejs.access.log;
error_log /var/log/nginx/nodejs.error.log;
location / {
proxy_pass http://nodejs_backend;
# HTTP 版本
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;
proxy_set_header Connection "";
# 逾時
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# 緩衝
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
}
location /health {
access_log off;
proxy_pass http://nodejs_backend/health;
}
}
6.2. Python Flask/Django 應用程式
後端(app.py):
from flask import Flask, jsonify, request
import os
app = Flask(name)
PORT = int(os.environ.get('PORT', 5000))
@app.route('/')
def home():
return jsonify({
'message': 'Hello from Python',
'server': f'localhost:{PORT}',
'headers': dict(request.headers)
})
@app.route('/api/data')
def get_data():
return jsonify([
{'id': 1, 'value': 'Data 1'},
{'id': 2, 'value': 'Data 2'}
])
@app.route('/health')
def health():
return jsonify({'status': 'ok'}), 200
if name == 'main':
app.run(host='0.0.0.0', port=PORT)
Nginx 設定:
upstream python_backend {
server localhost:5000;
server localhost:5001;
server localhost:5002;
}
server {
listen 80;
server_name python.example.com;
client_max_body_size 10M;
location / {
proxy_pass http://python_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;
# Python 應用程式可能較慢
proxy_read_timeout 300s;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
}
}
6.3. PHP 應用程式與 PHP-FPM
Nginx 設定:
upstream php_backend {
server unix:/var/run/php/php8.1-fpm.sock;
# 或
# server localhost:9000;
}
server {
listen 80;
server_name php.example.com;
root /var/www/php;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass php_backend;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# 標頭
fastcgi_param HTTP_X_REAL_IP $remote_addr;
fastcgi_param HTTP_X_FORWARDED_FOR $proxy_add_x_forwarded_for;
fastcgi_param HTTP_X_FORWARDED_PROTO $scheme;
}
location ~ /\.ht {
deny all;
}
}
6.4. 微服務架構
# 使用者服務
upstream user_service {
server user1.internal:8001;
server user2.internal:8001;
}
訂單服務
upstream order_service {
server order1.internal:8002;
server order2.internal:8002;
}
付款服務
upstream payment_service {
server payment1.internal:8003;
server payment2.internal:8003;
}
產品服務
upstream product_service {
server product1.internal:8004;
server product2.internal:8004;
}
server {
listen 80;
server_name api.example.com;
# 共用標頭
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;
proxy_set_header X-Request-ID $request_id;
location /api/users/ {
proxy_pass http://user_service/;
}
location /api/orders/ {
proxy_pass http://order_service/;
}
location /api/payments/ {
proxy_pass http://payment_service/;
}
location /api/products/ {
proxy_pass http://product_service/;
}
}
7. 練習題
練習1:基本反向代理
建立一個簡單的 Node.js/Python 伺服器,監聽連接埠 3000將 Nginx 設定為反向代理測試並確認標頭是否正確傳遞
練習2:多個後端
在連接埠 3000、3001、3002 上各執行一個應用程式實例設定採用輪詢的 upstream測試負載均衡(查看日誌以確認請求分配情況)
練習3:黏性會話
設定採用 ip_hash 的 upstream測試相同客戶端是否始終連到同一後端與輪詢進行比較
練習4:健康檢查
使用 max_fails 和 fail_timeout 設定被動健康檢查停止一個後端伺服器確認 Nginx 自動將流量路由到健康的伺服器重新啟動伺服器並確認流量恢復正常
練習5:微服務
建立 2-3 個簡單的 API(可使用模擬)設定 Nginx 根據 URL 路徑路由請求:/api/users→ 使用者服務/api/products→ 產品服務
測試路由
練習6:WebSocket 代理
建立一個簡單的 WebSocket 伺服器將 Nginx 設定為 WebSocket 代理測試連線與訊息傳遞
8. 疑難排解
8.1. 常見問題
1. 502 Bad Gateway:
# 原因:後端未執行或無法連線
檢查後端
查看 Nginx 錯誤日誌
sudo tail -f /var/log/nginx/error.log
檢查防火牆
sudo ufw status
2. 504 Gateway Timeout:
# 原因:後端回應時間過長
修正:增加逾時時間
location / {
proxy_pass http://backend;
proxy_read_timeout 300s;
proxy_connect_timeout 300s;
}
3. 標頭未傳遞:
# 在後端驗證標頭
記錄請求標頭
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;
4. 大型上傳失敗:
# 增加 client_max_body_size
http {
client_max_body_size 100M;
}
5. WebSocket 連線失敗:
# 必須有 Upgrade 標頭
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
8.2. 除錯指令
# 測試上游連線
curl -v http://localhost:3000
檢查 Nginx 設定
sudo nginx -t
重新載入 Nginx
sudo systemctl reload nginx
即時監看錯誤日誌
sudo tail -f /var/log/nginx/error.log
查看上游狀態(需啟用 stub_status)
curl http://localhost/nginx_status
使用特定標頭測試
curl -H "Host: example.com" http://localhost
測試代理標頭
curl -H "X-Forwarded-For: 1.2.3.4" http://localhost
9. 最佳實踐
9.1. 設定
使用 upstream 區塊:
# 推薦
upstream backend {
server localhost:3000;
}
不推薦(無故障轉移或負載均衡)
location / {
proxy_pass http://localhost:3000;
}
設定適當的逾時:
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
啟用 keepalive:
upstream backend {
server localhost:3000;
keepalive 32;
}
location / {
proxy_http_version 1.1;
proxy_set_header Connection "";
}
使用健康檢查:
server localhost:3000 max_fails=3 fail_timeout=30s;
9.2. 安全性
不暴露內部架構:
proxy_hide_header X-Powered-By;
限制請求大小:
client_max_body_size 10M;
速率限制:
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
location /api/ {
limit_req zone=api burst=20;
}
9.3. 效能
緩衝區設定:
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
快取:
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m;
location / {
proxy_cache my_cache;
proxy_cache_valid 200 10m;
}
總結
在本課中,您學到了:
✅ 反向代理的概念與使用場景✅ proxy_pass 設定與路由✅ 代理標頭與 X-Forwarded 標頭✅ 上游伺服器與負載均衡✅ 健康檢查與監控✅ Node.js、Python 和 PHP 的實際應用範例
下一課:我們將深入探討負載均衡——演算法、策略與進階設定。