摘要:本文系统讲解在银河麒麟服务器操作系统上配置 Nginx 正向代理、反向代理及负载均衡的完整流程。涵盖 SSL 终止与 SSL 透传、权重负载均衡实战案例及自动化压力测试脚本,帮助运维人员快速掌握企业级 Nginx 代理配置与高可用部署方案。

关键词: 银河麒麟;Nginx 代理配置;负载均衡实战;SSL 终止与透传;正向代理与反向代理

1. 引言

1.1 文档概述

本文档旨在指导在银河麒麟服务器操作系统上使用Nginx配置正向代理与反向代理服务。文档涵盖基础概念、配置步骤及常见场景示例。通过本文档可以快速实现网络请求的转发与负载均衡。

正向代理:客户端通过代理服务器访问外部资源,常用于内网机器访问互联网或客户端统一通过代理服务器上网(需结合身份验证)。

反向代理:客户端请求由代理服务器转发到后端服务,常用于隐藏真实服务器、实现负载均衡等。

1.2 适用范围

本文档面向具有Linux操作系统使用经验的人员、麒麟软件一线工程师及相关技术人员等,实现在银河麒麟服务器操作系统上使用Nginx配置正向代理与反向代理服务。

2. 配置前准备工作

在开始配置之前,请确保您的服务器满足以下最低配置要求:

配置项最低配置推荐生产环境配置
CPU2核4核或以上
内存2GB4GB或以上(高并发场景需要更多)
存储20GB可用空间(日志文件会占用空间)50GB+(SSD推荐,特别是高流量场景)
操作系统银河麒麟服务器操作系统 V10银河麒麟服务器操作系统 V10
网络具备公网或内网访问能力具备公网或内网访问能力

3. 配置步骤

3.1 Nginx安装与基本配置

3.1.1 安装Nginx

使用以下命令安装并启动Nginx服务:

# 安装Nginx
yum install nginx -y

# 启动Nginx
systemctl start nginx

# 设置Nginx开机自启动
systemctl enable nginx
3.1.2 防火墙配置

开放HTTP/HTTPS端口,确保外部可以访问Nginx服务:

# 开放HTTP/HTTPS端口
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https

# 重新加载防火墙规则
firewall-cmd --reload
3.1.3 验证安装

在浏览器中访问 http://<服务器IP>,若看到Nginx欢迎页即表示安装成功。

3.2 正向代理配置

3.2.1 应用场景
场景说明
内网服务器访问外网内网机器通过代理服务器访问互联网资源,如软件包下载、API调用等
客户端统一上网所有客户端通过统一的代理服务器上网,便于管理和审计(需结合身份验证)
3.2.2 HTTP正向代理配置

编辑Nginx配置文件 /etc/nginx/nginx.conf,在 http 块中添加以下内容:

server {
    listen 8080;  # 代理监听端口
    resolver 8.8.8.8;  # DNS解析服务器

    location / {
        proxy_pass http://$http_host$request_uri;  # 转发原始请求
        proxy_set_header Host $http_host;
    }
}

配置说明:

参数说明
listen 8080代理服务监听的端口,可根据需要修改
resolver 8.8.8.8DNS解析服务器地址,用于解析目标域名
proxy_pass将请求转发到原始目标地址
proxy_set_header设置请求头,确保后端服务能获取到原始Host信息
3.2.3 HTTPS正向代理配置(SSL证书转发)

正向代理支持HTTPS请求时,Nginx需要以**隧道模式(CONNECT方法)**工作,因为Nginx本身不解析HTTPS流量,而是通过CONNECT方法与目标服务器建立SSL隧道。配置如下:

server {
    listen 8080;
    resolver 8.8.8.8;

    # 处理HTTP请求
    location / {
        proxy_pass http://$http_host$request_uri;
        proxy_set_header Host $http_host;
    }

    # 处理HTTPS CONNECT隧道请求
    proxy_connect;
    proxy_connect_allow 443 563;
    proxy_connect_connect_timeout 10s;
    proxy_connect_read_timeout 10s;

    # 如果需要在代理层做SSL拦截(中间人代理),需加载ngx_http_proxy_connect_module
    # 并配置SSL证书用于解密和重新加密
    # server {
    #     listen 443 ssl;
    #     server_name proxy.example.com;
    #
    #     ssl_certificate     /etc/nginx/ssl/proxy.crt;
    #     ssl_certificate_key /etc/nginx/ssl/proxy.key;
    #
    #     location / {
    #         proxy_pass https://$http_host$request_uri;
    #         proxy_ssl_server_name on;
    #         proxy_ssl_name $http_host;
    #     }
    # }
}

配置说明:

参数说明
proxy_connect启用CONNECT方法支持,需编译时包含ngx_http_proxy_connect_module模块
proxy_connect_allow 443 563允许通过CONNECT连接的端口,443为HTTPS默认端口
proxy_connect_connect_timeoutCONNECT阶段连接超时时间
proxy_connect_read_timeoutCONNECT阶段读取超时时间

注意: 标准Nginx发行版默认不包含proxy_connect模块。如需支持HTTPS CONNECT隧道,需从源码编译Nginx时添加--add-module=/path/to/ngx_http_proxy_connect_module参数。若仅需透传HTTPS流量(不解密),上述CONNECT配置即可;若需做SSL中间人(MITM)解密审计,则需额外配置SSL证书并启用ssl_certificate。

3.2.4 重启Nginx生效
systemctl restart nginx
3.2.5 客户端使用代理

配置浏览器或系统网络代理为:http://<Nginx服务器IP>:8080。

操作案例:

假设Nginx服务器IP为 192.168.1.100,在客户端(如Windows)上配置代理:

  1. 打开 设置 → 网络和Internet → 代理
  2. 在 手动设置代理 中,开启 使用代理服务器
  3. 填写地址:192.168.1.100,端口:8080
  4. 点击 保存

配置完成后,访问 http://www.baidu.com,如果能够正常打开,则正向代理配置成功。

3.3 反向代理配置

3.3.1 基础反向代理示例

编辑Nginx配置文件 /etc/nginx/nginx.conf,在 http 块中添加以下内容:

server {
    listen 80;
    server_name example.com;  # 域名或IP

    location / {
        proxy_pass http://localhost:3000;  # 后端服务地址
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

配置说明:

参数说明
listen 80监听80端口,接收客户端请求
server_name服务器域名或IP地址
proxy_pass将请求转发到后端服务地址
proxy_set_header Host传递原始请求的Host头
proxy_set_header X-Real-IP传递客户端真实IP地址
3.3.2 HTTPS反向代理配置(SSL终止与SSL透传)

反向代理场景下,HTTPS有两种常见处理方式:SSL终止(SSL Termination)和SSL透传(SSL Pass-Through)。

方式一:SSL终止(SSL Termination)

Nginx在代理层解密HTTPS请求,然后将明文HTTP请求转发给后端服务。这种方式减轻了后端服务的SSL加解密负担,适合后端服务不直接暴露公网、且信任内网链路的场景。

server {
    listen 443 ssl;
    server_name example.com;

    # SSL证书配置
    ssl_certificate     /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;

    # SSL协议与加密套件优化
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    location / {
        proxy_pass http://localhost:3000;  # 后端接收明文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;  # 告知后端原始协议为https
    }
}

配置说明:

参数说明
listen 443 ssl监听443端口并启用SSL
ssl_certificate / ssl_certificate_key指定服务器证书和私钥文件路径
ssl_protocols限制允许的TLS协议版本,建议仅启用TLSv1.2和TLSv1.3
ssl_ciphers指定加密套件,HIGH:!aNULL:!MD5表示使用高强度套件并禁用匿名和MD5
ssl_prefer_server_ciphers优先使用服务端定义的加密套件顺序
proxy_pass http://...注意此处为http://而非https://,因为SSL已在Nginx层终止
X-Forwarded-Proto传递原始请求协议(https),便于后端做协议感知处理
方式二:SSL透传(SSL Pass-Through)

Nginx不解密HTTPS流量,而是将加密的TCP流直接透传给后端服务。后端服务自己处理SSL加解密。这种方式适用于后端服务需要端到端加密、或合规要求不允许中间节点接触明文数据的场景。

stream {
    upstream backend_ssl {
        server 10.0.0.1:443;  # 后端SSL服务地址
    }

    server {
        listen 443;
        proxy_pass backend_ssl;
        proxy_ssl on;                    # 启用Nginx到后端的SSL连接
        proxy_ssl_certificate     /etc/nginx/ssl/client.crt;  # 可选:客户端证书
        proxy_ssl_certificate_key /etc/nginx/ssl/client.key;
        proxy_ssl_server_name on;
        proxy_ssl_name backend.internal.example.com;  # SNI名称
        proxy_ssl_verify off;           # 是否验证后端证书(生产环境建议on)
    }
}

配置说明:

参数说明
stream使用Nginx的stream模块(四层TCP/UDP代理),而非http模块
proxy_pass将TCP流量转发到后端SSL服务
proxy_ssl on启用Nginx到后端服务器的SSL连接
proxy_ssl_server_name on启用SNI(Server Name Indication),用于后端多域名场景
proxy_ssl_name指定SNI中的服务器名称,需与后端证书域名匹配

SSL终止 vs SSL透传 选择建议:

  • 如果后端服务性能有限、或需要Nginx统一管理SSL证书 → 选择SSL终止
  • 如果合规要求端到端加密、或后端服务需要获取客户端证书信息 → 选择SSL透传
  • 注意:SSL透传模式下,Nginx无法基于HTTP协议做路由(如location匹配),只能基于IP和端口转发
3.3.3 测试配置并重启
# 检查配置文件语法
nginx -t

# 重启Nginx
systemctl restart nginx
3.3.4 操作案例:反向代理Node.js应用

假设我们有一个运行在 http://localhost:3000 的Node.js应用,希望通过Nginx反向代理对外提供服务。

步骤1:启动Node.js应用

// app.js
const http = require('http');

const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Hello from Node.js!\n');
});

server.listen(3000, () => {
  console.log('Server running at http://localhost:3000/');
});
node app.js

步骤2:配置Nginx反向代理

按照上述配置,将 proxy_pass 指向 http://localhost:3000。

步骤3:访问测试

在浏览器中访问 http://<服务器IP>,如果看到 Hello from Node.js!,则反向代理配置成功。

3.5 负载均衡配置

Nginx 的 upstream 模块可以将请求分发到多台后端服务器,实现负载均衡,提升系统可用性和并发处理能力。

3.5.1 upstream 模块基本语法
upstream backend {
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}

server {
    listen 80;
    location / {
        proxy_pass http://backend;
    }
}
3.5.2 轮询(默认)

请求按顺序依次分发到每台后端服务器,适合各服务器性能相近的场景。

配置示例:

upstream backend {
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}

适用场景: 所有后端服务器硬件配置相同、处理能力均衡,且请求处理时间相近的普通 Web 应用。

3.5.3 权重(weight)

通过 weight 参数指定每台服务器的权重,权重越高分配的请求越多,适合服务器性能不均的场景。

配置示例:

upstream backend {
    server 192.168.1.10:8080 weight=3;
    server 192.168.1.11:8080 weight=2;
    server 192.168.1.12:8080 weight=1;
}

上述配置中,服务器 192.168.1.10 每收到 3 个请求,192.168.1.11 收到 2 个,192.168.1.12 收到 1 个。

适用场景: 后端服务器配置不同(如 CPU、内存差异较大),需要按性能比例分配流量;或某台服务器需要承担更多业务流量。

3.5.4 IP Hash(ip_hash)

根据客户端 IP 的哈希值分配请求,同一 IP 的请求始终转发到同一台后端服务器,适用于需要保持会话(Session)的场景。

配置示例:

upstream backend {
    ip_hash;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}

适用场景: 有状态应用(如购物车、用户登录 Session 存储在本地内存),需要保证同一用户的请求始终由同一台后端处理;或需要实现简单的会话粘滞。

3.5.5 健康检查与故障转移

Nginx 默认会对 upstream 中的服务器进行被动健康检查——如果某台服务器响应超时或返回错误,Nginx 会自动将其标记为不可用,并将请求转发到其他可用服务器。

upstream backend {
    server 192.168.1.10:8080 max_fails=3 fail_timeout=30s;
    server 192.168.1.11:8080 max_fails=3 fail_timeout=30s;
    server 192.168.1.12:8080 backup;
}
  • max_fails:允许的最大失败次数,超过后标记为不可用。
  • fail_timeout:标记不可用后的冷却时间。
  • backup:标记为备用服务器,仅在主服务器全部不可用时启用。

主动健康检查(health_check)

Nginx Plus(商业版)提供了 health_check 指令,支持主动健康检查——Nginx 会定期主动向后端服务器发送探测请求,而非等待用户请求失败后才判定。开源版可通过 nginx-upstream-check-module 第三方模块实现类似功能。

upstream backend {
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
}

server {
    listen 80;
    location / {
        proxy_pass http://backend;
        health_check interval=5s fails=3 passes=2 uri=/health;
    }
}

参数说明:

参数默认值说明
interval5s两次健康检查之间的时间间隔
fails1连续失败次数达到该值后,标记服务器为不可用
passes1连续成功次数达到该值后,恢复服务器为可用
uri/健康检查请求的 URI,后端需返回 2xx/3xx 状态码
match—自定义匹配规则,可校验响应体或头部
主动检查 vs 被动检查对比
特性被动检查(默认)主动检查(health_check)
探测方式依赖用户请求触发Nginx 定时主动发送探测请求
发现故障速度慢(需等到用户请求失败)快(可在请求到来前发现)
后端恢复检测需等待用户请求再次触发定时探测,恢复后自动加入
额外流量无有(需后端提供健康检查端点)
配置复杂度低(仅需 max_fails/fail_timeout)中(需额外部署 /health 端点)
适用版本Nginx 开源版Nginx Plus 或第三方模块
适用场景
  • 主动检查:适合对可用性要求高的生产环境,尤其是后端服务重启频繁或需要快速感知故障的场景(如微服务架构、Kubernetes 后端)。
  • 被动检查:适合小型项目或后端稳定的场景,配置简单且不产生额外探测流量。

建议:在生产环境中,可将主动检查与被动检查结合使用——主动检查快速发现故障,被动检查作为兜底保障。

3.5.6 实战案例:Nginx 权重负载均衡

下面通过一个完整的实战案例,演示如何配置 Nginx 权重负载均衡,并验证请求按比例分发。

步骤一:模拟两个后端服务

使用 Python 启动两个简单的 HTTP 服务,分别监听 8081 和 8082 端口,返回不同的标识以便区分:

# 终端 1:启动后端服务 A(端口 8081)
python3 -m http.server 8081 --bind 127.0.0.1
# 终端 2:启动后端服务 B(端口 8082)
python3 -m http.server 8082 --bind 127.0.0.1

如果希望返回更明确的标识,可以用以下 Python 脚本替代:

# server_a.py — 后端服务 A(端口 8081)
from http.server import HTTPServer, BaseHTTPRequestHandler

class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-Type', 'text/plain; charset=utf-8')
        self.end_headers()
        self.wfile.write(b'Response from Server A (weight=2)\n')

HTTPServer(('127.0.0.1', 8081), Handler).serve_forever()
# server_b.py — 后端服务 B(端口 8082)
from http.server import HTTPServer, BaseHTTPRequestHandler

class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-Type', 'text/plain; charset=utf-8')
        self.end_headers()
        self.wfile.write(b'Response from Server B (weight=1)\n')

HTTPServer(('127.0.0.1', 8082), Handler).serve_forever()

分别运行:python3 server_a.py 和 python3 server_b.py

步骤二:配置 Nginx 权重负载均衡

编辑 Nginx 配置文件(如 /etc/nginx/conf.d/weighted-lb.conf):

upstream backend {
    server 127.0.0.1:8081 weight=2;
    server 127.0.0.1:8082 weight=1;
}

server {
    listen 80;
    server_name localhost;

    location / {
        proxy_pass http://backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

配置说明:

  • weight=2:服务器 A(8081)权重为 2,每 3 个请求中收到 2 个。
  • weight=1:服务器 B(8082)权重为 1,每 3 个请求中收到 1 个。
  • 请求分发比例为 2:1。

重载 Nginx 使配置生效:

sudo nginx -t          # 检查配置语法
sudo nginx -s reload   # 平滑重载

步骤三:测试请求分发比例

使用 curl 循环发送 30 次请求,统计返回结果:

# 循环请求 30 次,提取响应内容
for i in $(seq 1 30); do
    curl -s http://localhost/
done

为了更直观地统计比例,可以用以下脚本:

# 统计脚本:发送 30 次请求并计数
echo "A_count=0; B_count=0" > /tmp/count.txt
for i in $(seq 1 30); do
    result=$(curl -s http://localhost/)
    if echo "$result" | grep -q "Server A"; then
        echo "请求 $i → Server A"
        A_count=$((A_count + 1))
    else
        echo "请求 $i → Server B"
        B_count=$((B_count + 1))
    fi
done
echo "---"
echo "Server A (weight=2): $A_count 次"
echo "Server B (weight=1): $B_count 次"

预期结果:

由于权重比为 2:1,30 次请求的分布大致如下:

后端服务权重预期请求数实际示例
Server A(8081)2约 20 次19~21 次
Server B(8082)1约 10 次9~11 次

输出示例:

请求 1 → Server A
请求 2 → Server A
请求 3 → Server B
请求 4 → Server A
请求 5 → Server A
请求 6 → Server B
...
---
Server A (weight=2): 20 次
Server B (weight=1): 10 次

说明: Nginx 的权重分发是统计意义上的比例,并非严格的「每 3 个请求中恰好 2 个给 A、1 个给 B」。短时间内的少量请求可能存在波动,但请求次数越多(如 100 次以上),比例越接近 2:1。

步骤四:验证权重调整效果

尝试修改权重,观察分发比例变化:

upstream backend {
    server 127.0.0.1:8081 weight=3;
    server 127.0.0.1:8082 weight=1;
}

重载 Nginx 后再次测试,此时比例应接近 3:1(30 次请求中 A 约 22~23 次,B 约 7~8 次)。

步骤五:自动化压力测试与分发比例统计

除了手动循环测试,还可以使用 ab(Apache Bench)或 curl 编写自动化脚本,批量发送请求并精确统计分发比例。

方式一:使用 ab 进行压力测试并统计

ab 是 Apache 自带的 HTTP 压力测试工具,可以快速发送大量并发请求。以下脚本先使用 ab 发送 300 个请求(并发 10),然后通过分析 Nginx 访问日志来统计各后端服务器的请求分发比例:

#!/bin/bash
# 自动化压力测试脚本 — 使用 ab + 日志分析统计分发比例

# 配置参数
TOTAL_REQUESTS=300
CONCURRENCY=10
TARGET_URL="http://localhost/"
NGINX_LOG="/var/log/nginx/access.log"

echo "=========================================="
echo " Nginx 权重负载均衡 — 压力测试脚本"
echo "=========================================="
echo "目标 URL: $TARGET_URL"
echo "请求总数: $TOTAL_REQUESTS"
echo "并发数:   $CONCURRENCY"
echo ""

# 1. 清空 Nginx 访问日志(需要 sudo 权限)
echo "[1/4] 清空 Nginx 访问日志..."
sudo truncate -s 0 "$NGINX_LOG"
echo "   ✓ 日志已清空"
echo ""

# 2. 使用 ab 发送压力测试请求
echo "[2/4] 开始压力测试($TOTAL_REQUESTS 请求,并发 $CONCURRENCY)..."
ab -n "$TOTAL_REQUESTS" -c "$CONCURRENCY" "$TARGET_URL" > /tmp/ab_result.txt 2>&1
echo "   ✓ 压力测试完成"
echo ""

# 3. 从 Nginx 日志中统计各后端端口的分发次数
echo "[3/4] 分析请求分发比例..."
SERVER_A_COUNT=$(grep -c ":8081" "$NGINX_LOG")
SERVER_B_COUNT=$(grep -c ":8082" "$NGINX_LOG")
TOTAL_COUNT=$((SERVER_A_COUNT + SERVER_B_COUNT))

# 4. 输出统计结果
echo "[4/4] 统计结果"
echo "------------------------------------------"
echo "后端服务          | 请求数 | 占比"
echo "------------------|--------|--------"
printf "Server A (8081)   | %6d | %5.1f%%\n" "$SERVER_A_COUNT" "$(echo "scale=1; $SERVER_A_COUNT * 100 / $TOTAL_COUNT" | bc)"
printf "Server B (8082)   | %6d | %5.1f%%\n" "$SERVER_B_COUNT" "$(echo "scale=1; $SERVER_B_COUNT * 100 / $TOTAL_COUNT" | bc)"
echo "------------------|--------|--------"
printf "合计              | %6d | 100.0%%\n" "$TOTAL_COUNT"
echo ""

# 计算理论比例(基于 weight 配置)
echo "理论分发比例:Server A : Server B = 2 : 1(约 66.7% : 33.3%)"
echo ""

# 判断是否接近预期
if [ "$TOTAL_COUNT" -gt 0 ]; then
    A_PERCENT=$(echo "scale=1; $SERVER_A_COUNT * 100 / $TOTAL_COUNT" | bc)
    if [ "$(echo "$A_PERCENT >= 60" | bc)" -eq 1 ] && [ "$(echo "$A_PERCENT <= 73" | bc)" -eq 1 ]; then
        echo "✅ 测试通过:分发比例接近预期的 2:1(权重配置正确)"
    else
        echo "⚠️  测试结果偏差较大,请检查 Nginx 配置是否生效"
    fi
fi
echo "=========================================="

运行方式:

chmod +x test_weighted_lb.sh
./test_weighted_lb.sh

输出示例:

==========================================
 Nginx 权重负载均衡 — 压力测试脚本
==========================================
目标 URL: http://localhost/
请求总数: 300
并发数:   10

[1/4] 清空 Nginx 访问日志...
   ✓ 日志已清空

[2/4] 开始压力测试(300 请求,并发 10)...
   ✓ 压力测试完成

[3/4] 分析请求分发比例...
[4/4] 统计结果
------------------------------------------
后端服务          | 请求数 | 占比
------------------|--------|--------
Server A (8081)   |    198 |  66.0%
Server B (8082)   |    102 |  34.0%
------------------|--------|--------
合计              |    300 | 100.0%

理论分发比例:Server A : Server B = 2 : 1(约 66.7% : 33.3%)

✅ 测试通过:分发比例接近预期的 2:1(权重配置正确)
==========================================
方式二:纯 curl 自动化统计脚本(无需 ab)

如果环境中未安装 ab,也可以使用纯 curl 脚本完成统计,并自动计算比例和偏差:

#!/bin/bash
# 纯 curl 自动化压力测试脚本 — 请求计数、比例计算与结果输出

# 配置参数
TOTAL_REQUESTS=100
TARGET_URL="http://localhost/"
SERVER_A_PORT=8081
SERVER_B_PORT=8082

# 初始化计数器
SERVER_A_COUNT=0
SERVER_B_COUNT=0
OTHER_COUNT=0

echo "=========================================="
echo " curl 自动化分发比例统计"
echo "=========================================="
echo "请求总数: $TOTAL_REQUESTS"
echo ""

# 发送请求并统计
for ((i=1; i<=TOTAL_REQUESTS; i++)); do
    # 发送请求,仅获取响应状态码和响应体前 50 字符
    RESPONSE=$(curl -s -o /tmp/curl_response.txt -w "%{http_code}" "$TARGET_URL")
    STATUS_CODE="$RESPONSE"
    
    # 根据响应内容判断由哪个后端处理
    if grep -q "Server A" /tmp/curl_response.txt 2>/dev/null; then
        SERVER_A_COUNT=$((SERVER_A_COUNT + 1))
        SERVER_LABEL="Server A"
    elif grep -q "Server B" /tmp/curl_response.txt 2>/dev/null; then
        SERVER_B_COUNT=$((SERVER_B_COUNT + 1))
        SERVER_LABEL="Server B"
    else
        OTHER_COUNT=$((OTHER_COUNT + 1))
        SERVER_LABEL="Unknown"
    fi
    
    # 每 10 个请求输出一次进度
    if [ $((i % 10)) -eq 0 ]; then
        printf "  进度: %3d/%d 请求完成\n" "$i" "$TOTAL_REQUESTS"
    fi
done

echo ""

# 计算比例
TOTAL_PROCESSED=$((SERVER_A_COUNT + SERVER_B_COUNT))

# 输出统计结果表格
echo "=========================================="
echo " 分发比例统计结果"
echo "=========================================="
printf "%-20s %8s %8s\n" "后端服务" "请求数" "占比"
echo "---------------------- -------- --------"
A_PERCENT=$(echo "scale=2; $SERVER_A_COUNT * 100 / $TOTAL_REQUESTS" | bc)
B_PERCENT=$(echo "scale=2; $SERVER_B_COUNT * 100 / $TOTAL_REQUESTS" | bc)
printf "%-20s %8d %7.1f%%\n" "Server A (weight=2)" "$SERVER_A_COUNT" "$A_PERCENT"
printf "%-20s %8d %7.1f%%\n" "Server B (weight=1)" "$SERVER_B_COUNT" "$B_PERCENT"
echo "---------------------- -------- --------"
printf "%-20s %8d %7.1f%%\n" "合计" "$TOTAL_REQUESTS" "100.0"
echo ""

# 计算理论值与实际值的偏差
THEORETICAL_A=$(echo "scale=2; $TOTAL_REQUESTS * 2 / 3" | bc)
THEORETICAL_B=$(echo "scale=2; $TOTAL_REQUESTS * 1 / 3" | bc)
DEVIATION_A=$(echo "scale=2; $SERVER_A_COUNT - $THEORETICAL_A" | bc)
DEVIATION_B=$(echo "scale=2; $SERVER_B_COUNT - $THEORETICAL_B" | bc)

echo "偏差分析:"
printf "  Server A: 理论值 %.1f,实际 %d,偏差 %+.1f\n" "$THEORETICAL_A" "$SERVER_A_COUNT" "$DEVIATION_A"
printf "  Server B: 理论值 %.1f,实际 %d,偏差 %+.1f\n" "$THEORETICAL_B" "$SERVER_B_COUNT" "$DEVIATION_B"
echo ""

# 结论判断
if [ "$TOTAL_PROCESSED" -gt 0 ]; then
    RATIO=$(echo "scale=2; $SERVER_A_COUNT / $SERVER_B_COUNT" | bc)
    echo "实际分发比例(A:B)= $RATIO : 1"
    echo "理论分发比例(A:B)= 2 : 1"
    echo ""
    if [ "$(echo "$RATIO >= 1.5" | bc)" -eq 1 ] && [ "$(echo "$RATIO <= 2.5" | bc)" -eq 1 ]; then
        echo "✅ 结论:权重负载均衡配置正确,请求按 2:1 比例分发"
    else
        echo "⚠️  结论:分发比例偏差较大,请检查 Nginx 配置"
    fi
fi
echo "=========================================="

运行方式:

chmod +x curl_lb_test.sh
./curl_lb_test.sh

输出示例:

==========================================
 curl 自动化分发比例统计
==========================================
请求总数: 100

   进度:  10/100 请求完成
   进度:  20/100 请求完成
   ...
   进度: 100/100 请求完成

==========================================
 分发比例统计结果
==========================================
后端服务                请求数      占比
---------------------- -------- --------
Server A (weight=2)         66    66.0%
Server B (weight=1)         34    34.0%
---------------------- -------- --------
合计                       100   100.0%

偏差分析:
  Server A: 理论值 66.7,实际 66,偏差 -0.7
  Server B: 理论值 33.3,实际 34,偏差 +0.7

实际分发比例(A:B)= 1.94 : 1
理论分发比例(A:B)= 2 : 1

✅ 结论:权重负载均衡配置正确,请求按 2:1 比例分发
==========================================

提示: 以上脚本均支持调整 TOTAL_REQUESTS 变量来增加请求数量。请求次数越多(建议 300 次以上),统计结果越接近理论比例。如果修改了权重配置(如改为 3:1),只需更新脚本中的理论比例说明即可。

3.4 高级配置与优化

3.4.1 连接超时设置

通过 proxy_connect_timeout、proxy_read_timeout 和 proxy_send_timeout 指令可以控制Nginx与后端服务器之间的连接超时时间,防止长时间占用连接资源。

location / {
    proxy_pass http://backend;
    
    # 与后端服务器建立连接的超时时间(默认60秒)
    proxy_connect_timeout 30s;
    
    # 从后端服务器读取响应的超时时间(默认60秒)
    proxy_read_timeout 60s;
    
    # 向后端服务器发送请求的超时时间(默认60秒)
    proxy_send_timeout 30s;
}

参数说明:

参数默认值推荐值说明
proxy_connect_timeout60s10–30s与后端建立TCP连接的超时时间,网络不稳定时可适当增大
proxy_read_timeout60s30–60s两次连续读操作之间的间隔超时,非整个请求的总超时
proxy_send_timeout60s30–60s两次连续写操作之间的间隔超时

注意: 超时时间不宜设置过长,否则会导致大量连接堆积,耗尽系统资源;也不宜过短,避免正常慢请求被误杀。

3.4.2 缓冲区优化

proxy_buffering 及相关指令控制Nginx是否缓冲后端服务器的响应数据,合理配置可显著提升吞吐量。

location / {
    proxy_pass http://backend;
    
    # 开启响应缓冲(默认开启)
    proxy_buffering on;
    
    # 单个缓冲区大小(默认4k或8k,与系统内存页大小一致)
    proxy_buffer_size 4k;
    
    # 缓冲区数量与每个缓冲区大小
    proxy_buffers 8 4k;
    
    # 响应超过此大小时写入临时文件
    proxy_max_temp_file_size 1024m;
    
    # 临时文件每次写入的数据大小
    proxy_temp_file_write_size 64k;
}

配置建议:

  • 静态内容或API响应较小:保持 proxy_buffering on,使用较小的缓冲区即可,减少磁盘I/O。
  • 大文件下载或流媒体:可关闭缓冲(proxy_buffering off),让客户端直接接收后端响应,降低内存占用。
  • 高并发场景:适当增加 proxy_buffers 的数量和大小,避免因缓冲区不足导致响应阻塞。
3.4.3 缓存配置

利用 proxy_cache 可以缓存后端响应,减少重复请求对后端服务的压力,大幅提升响应速度。

# 在 http 块中定义缓存路径和共享内存区域
http {
    proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m
                     max_size=1g inactive=60m use_temp_path=off;
    
    server {
        listen 80;
        server_name example.com;
        
        location / {
            proxy_pass http://backend;
            
            # 启用缓存,引用上面定义的缓存区域
            proxy_cache my_cache;
            
            # 缓存有效期(根据状态码分别设置)
            proxy_cache_valid 200 302 60m;
            proxy_cache_valid 404 1m;
            
            # 缓存键(默认包含域名+请求URI)
            proxy_cache_key "$scheme$request_method$host$request_uri";
            
            # 跳过缓存的条件
            proxy_no_cache $cookie_nocache $arg_nocache;
            proxy_cache_bypass $cookie_nocache $arg_nocache;
            
            # 向后端添加缓存状态头,便于调试
            add_header X-Cache-Status $upstream_cache_status;
        }
    }
}

参数详解:

参数说明
proxy_cache_path定义缓存存储路径、目录层级、共享内存大小、最大容量和过期时间
keys_zone共享内存区域名称及大小,用于存储缓存键和元数据(1MB约可存储8000个键)
levels=1:2缓存目录层级,分散文件存储避免单目录文件过多
inactive缓存项在指定时间内未被访问则自动清除
proxy_cache_valid按响应状态码设置缓存有效期
proxy_cache_key自定义缓存键,默认包含域名、协议、请求方法和URI
X-Cache-Status响应头,取值为 HIT(命中)、MISS(未命中)、BYPASS(跳过)等

生产建议: 缓存配置应结合业务场景灵活调整。对于动态接口建议设置较短有效期或按参数跳过缓存;对于静态资源可设置较长有效期,并配合 proxy_cache_purge 模块实现手动清理。

4. 常见问题与排查

本章节针对正向代理和反向代理配置中可能遇到的典型问题,分别列出问题现象、可能原因和具体的排查步骤与命令。

4.1 正向代理常见问题

4.1.1 代理无法连接

问题现象:

  • 客户端配置代理后,浏览器或应用提示「无法连接到代理服务器」
  • curl 请求报错 Could not connect to proxy 或 Connection refused

可能原因:

  1. Nginx 代理服务未启动或已崩溃
  2. 代理端口被防火墙拦截
  3. Nginx 监听地址配置错误(如只绑定了 127.0.0.1 而非 0.0.0.0)
  4. 客户端代理地址或端口填写错误

排查步骤与命令:

# 1. 检查 Nginx 进程是否运行
ps aux | grep nginx

# 2. 检查 Nginx 监听端口(假设代理端口为 3128)
netstat -tulnp | grep 3128
ss -tlnp | grep 3128

# 3. 检查防火墙规则
iptables -L -n | grep 3128
firewall-cmd --list-ports   # CentOS/RHEL
ufw status                  # Ubuntu/Debian

# 4. 查看 Nginx 错误日志
tail -100 /var/log/nginx/error.log

# 5. 测试本地连通性
curl -x http://127.0.0.1:3128 http://example.com

# 6. 检查 Nginx 配置中 listen 指令
grep -n "listen" /etc/nginx/nginx.conf /etc/nginx/conf.d/*.conf
4.1.2 正向代理 HTTPS 请求失败(SSL 证书问题)

问题现象:

  • HTTP 请求正常,但 HTTPS 请求报错 SSL certificate problem 或 TLS handshake failed
  • 浏览器提示「代理服务器证书错误」

可能原因:

  1. Nginx 未配置 HTTPS 正向代理所需的 proxy_ssl 指令
  2. 后端 SSL 证书过期或无效
  3. Nginx 编译时未包含 ngx_http_proxy_connect_module 模块
  4. 客户端未信任代理服务器的 CA 证书

排查步骤与命令:

# 1. 检查 Nginx 是否支持 CONNECT 方法(HTTPS 正向代理必需)
nginx -V 2>&1 | grep -i connect

# 2. 检查正向代理配置中是否包含以下关键指令
grep -A 10 "proxy_connect" /etc/nginx/conf.d/*.conf

# 3. 测试 HTTPS 请求并查看详细错误
curl -v -x http://127.0.0.1:3128 https://www.baidu.com 2>&1 | grep -i "ssl\|certificate\|handshake"

# 4. 检查后端证书有效性
echo | openssl s_client -connect www.baidu.com:443 -servername www.baidu.com 2>/dev/null | openssl x509 -noout -dates

# 5. 查看 Nginx 错误日志中 SSL 相关错误
tail -100 /var/log/nginx/error.log | grep -i "ssl\|connect\|proxy"

典型配置修复示例:

server {
    listen 3128;
    
    # HTTP 正向代理
    location / {
        resolver 8.8.8.8;
        proxy_pass http://$http_host$request_uri;
        proxy_set_header Host $http_host;
    }
    
    # HTTPS 正向代理(需 ngx_http_proxy_connect_module)
    proxy_connect;
    proxy_connect_allow 443 563;
    proxy_connect_connect_timeout 10s;
    proxy_connect_data_timeout 30s;
    
    location / {
        proxy_pass http://$http_host$request_uri;
        proxy_set_header Host $http_host;
    }
}

4.2 反向代理常见问题

4.2.1 502 Bad Gateway

问题现象:

  • 访问代理地址时浏览器返回 502 Bad Gateway
  • Nginx 错误日志中出现 upstream prematurely closed connection 或 no live upstreams

可能原因:

  1. 后端服务未启动或已崩溃
  2. 后端服务监听地址/端口与 proxy_pass 配置不匹配
  3. 后端服务响应超时
  4. 后端服务返回的响应头格式错误
  5. 后端服务连接数达到上限

排查步骤与命令:

# 1. 检查后端服务是否运行
systemctl status your-backend-service
netstat -tulnp | grep 8080   # 替换为实际后端端口

# 2. 直接访问后端服务(绕过 Nginx)
curl -v http://127.0.0.1:8080/health

# 3. 检查 Nginx 错误日志
tail -100 /var/log/nginx/error.log | grep -i "502\|upstream\|connect"

# 4. 检查 Nginx 配置中的 proxy_pass 地址
grep -n "proxy_pass" /etc/nginx/conf.d/*.conf

# 5. 测试后端连通性
telnet 127.0.0.1 8080
nc -zv 127.0.0.1 8080

# 6. 检查后端服务日志
journalctl -u your-backend-service --no-pager -n 50
4.2.2 504 Gateway Timeout

问题现象:

  • 访问代理地址时浏览器返回 504 Gateway Timeout
  • 请求长时间无响应后超时断开

可能原因:

  1. 后端服务处理请求时间过长,超过 Nginx 超时配置
  2. 后端服务在高并发下响应缓慢
  3. 网络延迟过高或丢包严重
  4. proxy_read_timeout / proxy_connect_timeout 配置过小

排查步骤与命令:

# 1. 检查当前 Nginx 超时配置
grep -n "timeout" /etc/nginx/nginx.conf /etc/nginx/conf.d/*.conf

# 2. 测试后端响应时间
time curl -v http://127.0.0.1:8080/api/test

# 3. 检查网络延迟
ping -c 10 <后端服务器IP>

# 4. 查看 Nginx 错误日志
tail -100 /var/log/nginx/error.log | grep -i "504\|timeout\|upstream timed out"

# 5. 调整超时配置(在 http/server/location 块中)
# proxy_connect_timeout 60s;
# proxy_read_timeout 120s;
# proxy_send_timeout 120s;
4.2.3 SSL 证书错误(反向代理 HTTPS)

问题现象:

  • 浏览器提示「您的连接不是私密连接」或 NET::ERR_CERT_COMMON_NAME_INVALID
  • curl 报错 SSL certificate problem: self-signed certificate 或 certificate has expired

可能原因:

  1. SSL 证书已过期
  2. 证书域名与访问域名不匹配
  3. 使用了自签名证书但客户端未信任
  4. 证书链不完整(缺少中间证书)
  5. Nginx 配置中证书路径错误

排查步骤与命令:

# 1. 检查证书有效期
openssl x509 -in /etc/nginx/ssl/your-cert.pem -noout -dates

# 2. 检查证书域名匹配
openssl x509 -in /etc/nginx/ssl/your-cert.pem -noout -subject -issuer
openssl x509 -in /etc/nginx/ssl/your-cert.pem -noout -ext subjectAltName

# 3. 验证证书链完整性
openssl verify -CAfile /etc/nginx/ssl/ca-bundle.crt /etc/nginx/ssl/your-cert.pem

# 4. 检查 Nginx 配置中的证书路径
grep -n "ssl_certificate" /etc/nginx/conf.d/*.conf

# 5. 测试 SSL 连接
echo | openssl s_client -connect 127.0.0.1:443 -servername yourdomain.com 2>/dev/null | grep -i "verify return code\|certificate chain"

# 6. 检查 Nginx 错误日志中的 SSL 错误
tail -100 /var/log/nginx/error.log | grep -i "ssl\|certificate\|PEM"

配置修复示例:

server {
    listen 443 ssl http2;
    server_name yourdomain.com;
    
    # 正确配置证书和私钥
    ssl_certificate     /etc/nginx/ssl/yourdomain.com.pem;
    ssl_certificate_key /etc/nginx/ssl/yourdomain.com.key;
    
    # 配置证书链(如果 CA 提供了中间证书)
    ssl_trusted_certificate /etc/nginx/ssl/ca-bundle.crt;
    
    # 推荐的安全配置
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    
    location / {
        proxy_pass http://backend_server;
    }
}

4.3 负载均衡常见问题

4.3.1 负载不均衡

问题现象:

  • 部分后端服务器负载过高,部分服务器空闲
  • 监控显示请求分布不均匀

可能原因:

  1. 使用了 ip_hash 但客户端 IP 分布不均
  2. 权重(weight)配置不合理
  3. 后端服务器性能差异大但未设置相应权重
  4. 长连接导致连接被固定到某台服务器

排查步骤与命令:

# 1. 查看当前 upstream 配置
grep -A 20 "upstream" /etc/nginx/conf.d/*.conf

# 2. 检查各后端服务器的连接数
for server in server1 server2 server3; do
    echo "=== $server ==="
    ssh $server "netstat -an | grep :8080 | wc -l"
done

# 3. 查看 Nginx 连接分布
curl http://127.0.0.1/nginx_status 2>/dev/null | grep "Active"

# 4. 检查后端服务器资源使用情况
for server in server1 server2 server3; do
    echo "=== $server ==="
    ssh $server "top -bn1 | head -5"
done

优化配置示例:

upstream backend {
    # 根据服务器性能设置不同权重
    server 192.168.1.10:8080 weight=5;   # 高性能服务器
    server 192.168.1.11:8080 weight=3;   # 中等性能
    server 192.168.1.12:8080 weight=2;   # 低性能
    
    # 启用最少连接算法(替代默认轮询)
    least_conn;
    
    # 最大失败次数和失败超时
    max_fails=3 fail_timeout=30s;
}
4.3.2 后端服务器健康检查失败

问题现象:

  • 部分后端服务器被标记为 down,请求被转发到其他服务器
  • 日志中出现 upstream server temporarily disabled

可能原因:

  1. 后端服务临时不可用(重启、部署中)
  2. 健康检查路径(health_check)配置错误
  3. 健康检查超时时间过短
  4. 后端服务返回非 2xx/3xx 状态码

排查步骤与命令:

# 1. 检查 Nginx 被动健康检查状态
tail -100 /var/log/nginx/error.log | grep -i "upstream\|disabled\|fail"

# 2. 手动测试健康检查端点
curl -v http://192.168.1.10:8080/health

# 3. 检查后端服务日志
journalctl -u backend-service --no-pager -n 30

# 4. 查看 Nginx 状态页面(需启用 status 模块)
curl http://127.0.0.1/status

# 5. 检查 max_fails 和 fail_timeout 配置
grep -B 5 -A 10 "upstream" /etc/nginx/conf.d/*.conf

健康检查配置示例:

upstream backend {
    server 192.168.1.10:8080 max_fails=3 fail_timeout=30s;
    server 192.168.1.11:8080 max_fails=3 fail_timeout=30s;
    server 192.168.1.12:8080 backup;  # 备用服务器
}

server {
    location / {
        proxy_pass http://backend;
        health_check interval=5s fails=3 passes=2 uri=/health;
    }
}

4.4 通用排查工具与技巧

以下命令适用于多种场景的快速诊断:

# 1. 实时查看 Nginx 错误日志
tail -f /var/log/nginx/error.log

# 2. 实时查看 Nginx 访问日志
tail -f /var/log/nginx/access.log | awk '{print $1, $7, $9}'

# 3. 测试 Nginx 配置语法
nginx -t

# 4. 重新加载 Nginx 配置(不中断服务)
nginx -s reload

# 5. 查看 Nginx 编译模块
nginx -V 2>&1

# 6. 查看系统资源使用
top -bn1 | head -10
free -h
df -h

# 7. 网络连接状态统计
netstat -an | grep -E ":(80|443|8080)" | awk '{print $6}' | sort | uniq -c

# 8. DNS 解析测试
nslookup your-backend-domain.com
dig your-backend-domain.com

4. 附录

4.1 常见问题排查

问题可能原因解决方案
代理无法访问Nginx服务未启动或防火墙未开放端口1. 检查Nginx日志:tail -f /var/log/nginx/error.log
2. 确认防火墙是否关闭,如果开启需要确保HTTP/HTTPS端口已开放
502 Bad Gateway后端服务未运行或代理地址错误1. 检查后端服务是否运行:netstat -tulnp | grep 8080
2. 检查代理地址是否正确
403 Forbidden权限配置问题检查Nginx配置中的 allow 和 deny 指令,确保客户端IP被允许访问
连接超时网络不通或后端服务响应慢1. 检查网络连通性:ping <后端服务器IP>
2. 增加 proxy_read_timeout 配置值

4.2 总结

通过本文档,您已经掌握了在银河麒麟服务器操作系统上使用Nginx配置正向代理和反向代理的基本方法。正向代理主要用于内网机器访问外网资源,而反向代理则常用于隐藏真实服务器、实现负载均衡和统一入口管理。

在实际生产环境中,建议根据业务需求进一步优化配置,如添加缓存、SSL证书、访问控制等,以提升性能和安全性。

安全配置建议:

  • 访问控制:使用 allow / deny 指令限制特定IP段的访问,或结合 ngx_http_auth_basic_module 实现基本认证;对于更细粒度的权限控制,可集成OAuth2或LDAP认证。
  • 日志审计:开启Nginx访问日志(access_log)和错误日志(error_log),并配置日志格式记录客户端IP、请求时间、请求方法、状态码和响应时间等关键字段,便于事后追溯和异常分析。
  • HTTPS加密:为代理服务配置SSL/TLS证书,使用 listen 443 ssl 启用HTTPS,防止中间人攻击和数据泄露。
  • 请求限流:使用 limit_req 和 limit_conn 模块限制单个IP的请求频率和并发连接数,防止恶意攻击和资源滥用。
Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐