Nginx代理服务配置完全指南:正向代理与反向代理实战
摘要:本文系统讲解在银河麒麟服务器操作系统上配置 Nginx 正向代理、反向代理及负载均衡的完整流程。涵盖 SSL 终止与 SSL 透传、权重负载均衡实战案例及自动化压力测试脚本,帮助运维人员快速掌握企业级 Nginx 代理配置与高可用部署方案。
关键词: 银河麒麟;Nginx 代理配置;负载均衡实战;SSL 终止与透传;正向代理与反向代理
1. 引言
1.1 文档概述
本文档旨在指导在银河麒麟服务器操作系统上使用Nginx配置正向代理与反向代理服务。文档涵盖基础概念、配置步骤及常见场景示例。通过本文档可以快速实现网络请求的转发与负载均衡。
正向代理:客户端通过代理服务器访问外部资源,常用于内网机器访问互联网或客户端统一通过代理服务器上网(需结合身份验证)。
反向代理:客户端请求由代理服务器转发到后端服务,常用于隐藏真实服务器、实现负载均衡等。
1.2 适用范围
本文档面向具有Linux操作系统使用经验的人员、麒麟软件一线工程师及相关技术人员等,实现在银河麒麟服务器操作系统上使用Nginx配置正向代理与反向代理服务。
2. 配置前准备工作
在开始配置之前,请确保您的服务器满足以下最低配置要求:
| 配置项 | 最低配置 | 推荐生产环境配置 |
|---|---|---|
| CPU | 2核 | 4核或以上 |
| 内存 | 2GB | 4GB或以上(高并发场景需要更多) |
| 存储 | 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.8 | DNS解析服务器地址,用于解析目标域名 |
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_timeout | CONNECT阶段连接超时时间 |
proxy_connect_read_timeout | CONNECT阶段读取超时时间 |
注意: 标准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)上配置代理:
- 打开 设置 → 网络和Internet → 代理
- 在 手动设置代理 中,开启 使用代理服务器
- 填写地址:
192.168.1.100,端口:8080 - 点击 保存
配置完成后,访问 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;
}
}
参数说明:
| 参数 | 默认值 | 说明 |
|---|---|---|
interval | 5s | 两次健康检查之间的时间间隔 |
fails | 1 | 连续失败次数达到该值后,标记服务器为不可用 |
passes | 1 | 连续成功次数达到该值后,恢复服务器为可用 |
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_timeout | 60s | 10–30s | 与后端建立TCP连接的超时时间,网络不稳定时可适当增大 |
proxy_read_timeout | 60s | 30–60s | 两次连续读操作之间的间隔超时,非整个请求的总超时 |
proxy_send_timeout | 60s | 30–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
可能原因:
- Nginx 代理服务未启动或已崩溃
- 代理端口被防火墙拦截
- Nginx 监听地址配置错误(如只绑定了
127.0.0.1而非0.0.0.0) - 客户端代理地址或端口填写错误
排查步骤与命令:
# 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 - 浏览器提示「代理服务器证书错误」
可能原因:
- Nginx 未配置 HTTPS 正向代理所需的
proxy_ssl指令 - 后端 SSL 证书过期或无效
- Nginx 编译时未包含
ngx_http_proxy_connect_module模块 - 客户端未信任代理服务器的 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
可能原因:
- 后端服务未启动或已崩溃
- 后端服务监听地址/端口与
proxy_pass配置不匹配 - 后端服务响应超时
- 后端服务返回的响应头格式错误
- 后端服务连接数达到上限
排查步骤与命令:
# 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 - 请求长时间无响应后超时断开
可能原因:
- 后端服务处理请求时间过长,超过 Nginx 超时配置
- 后端服务在高并发下响应缓慢
- 网络延迟过高或丢包严重
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
可能原因:
- SSL 证书已过期
- 证书域名与访问域名不匹配
- 使用了自签名证书但客户端未信任
- 证书链不完整(缺少中间证书)
- 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 负载不均衡
问题现象:
- 部分后端服务器负载过高,部分服务器空闲
- 监控显示请求分布不均匀
可能原因:
- 使用了
ip_hash但客户端 IP 分布不均 - 权重(
weight)配置不合理 - 后端服务器性能差异大但未设置相应权重
- 长连接导致连接被固定到某台服务器
排查步骤与命令:
# 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
可能原因:
- 后端服务临时不可用(重启、部署中)
- 健康检查路径(
health_check)配置错误 - 健康检查超时时间过短
- 后端服务返回非 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.log2. 确认防火墙是否关闭,如果开启需要确保HTTP/HTTPS端口已开放 |
| 502 Bad Gateway | 后端服务未运行或代理地址错误 | 1. 检查后端服务是否运行:netstat -tulnp | grep 80802. 检查代理地址是否正确 |
| 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的请求频率和并发连接数,防止恶意攻击和资源滥用。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐



所有评论(0)