Nginx反向代理+负载均衡实战:小白也能搭建高可用架构

admin 2026-01-26 02:04:21 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文深入解析Nginx反向代理与负载均衡实战,涵盖多种调度算法、健康检查及连接复用机制。通过电商与灰度发布案例提供生产级配置,并详述故障排查与监控方案,指导构建高可用服务架构。 综合评分: 91 文章分类: 安全建设,网络安全,解决方案


cover_image

Nginx反向代理+负载均衡实战:小白也能搭建高可用架构

点击关注 👉 点击关注 👉

马哥网络安全

2026年1月25日 17:01 河南

Nginx反向代理+负载均衡实战:小白也能搭建高可用架构

一、概述

1.1 背景介绍

2023年我带了个新人,让他搭个负载均衡,结果他配了半天,流量全跑到一台机器上,另外两台闲着。排查了一个小时,发现他把upstream里的server全写成了localhost。这事儿让我意识到,反向代理和负载均衡看着简单,坑还真不少。

对于很多刚入行的同学来说,”反向代理”这词听着就让人头大。其实没那么复杂:正向代理是代理客户端(比如VPN),反向代理是代理服务端。用户访问的是Nginx,Nginx再去访问真正的后端服务,用户根本不知道后端服务的存在。

负载均衡则是反向代理的进阶玩法。当一台后端服务器扛不住流量的时候,就需要多台服务器一起分担压力。Nginx负责把请求分发到不同的服务器上,这就是负载均衡。

1.2 技术特点

反向代理的价值

  • 隐藏后端服务器真实IP,增强安全性
  • 统一入口,便于管理和监控
  • SSL卸载,减轻后端压力
  • 静态资源缓存,减少后端请求
  • 请求过滤和限流

负载均衡的价值

  • 水平扩展,突破单机性能瓶颈
  • 高可用,单点故障不影响服务
  • 灵活调度,支持多种算法
  • 灰度发布,逐步迁移流量

1.3 适用场景

  • Web应用集群部署
  • API网关入口
  • 微服务架构流量分发
  • 静态资源与动态请求分离
  • 多数据中心流量调度
  • 蓝绿部署和灰度发布

1.4 环境要求

| 组件 | 版本 | 说明 | | — | — | — | | 操作系统 | Rocky Linux 9.4 / Ubuntu 24.04 LTS | 稳定的生产环境系统 | | Nginx | 1.26.2 | 建议使用stable分支 | | 后端服务 | 任意HTTP服务 | 示例用Tomcat 10.1.x | | 网络 | 内网互通 | Nginx与后端服务器网络延迟<1ms |

实验环境架构

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ┌─────────────────┐
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp; Client请求 &nbsp; &nbsp;│
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; └────────┬────────┘
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;▼
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ┌─────────────────┐
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp;Nginx负载均衡 &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp;192.168.1.10 &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; └────────┬────────┘
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;┌─────────────────┼─────────────────┐
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;▼ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ▼ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ▼
&nbsp; &nbsp; ┌─────────────┐ &nbsp; ┌─────────────┐ &nbsp; ┌─────────────┐
&nbsp; &nbsp; │ &nbsp;Backend 1 &nbsp;│ &nbsp; │ &nbsp;Backend 2 &nbsp;│ &nbsp; │ &nbsp;Backend 3 &nbsp;│
&nbsp; &nbsp; │ 192.168.1.11│ &nbsp; │ 192.168.1.12│ &nbsp; │ 192.168.1.13│
&nbsp; &nbsp; └─────────────┘ &nbsp; └─────────────┘ &nbsp; └─────────────┘

二、详细步骤

2.1 准备工作

2.1.1 安装Nginx

Rocky Linux 9

# 添加Nginx官方仓库
cat > /etc/yum.repos.d/nginx.repo <<&nbsp;'EOF'
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
EOF

# 安装Nginx
dnf install nginx -y

# 启动并设置开机自启
systemctl start nginx
systemctl&nbsp;enable&nbsp;nginx

# 检查版本
nginx -v

Ubuntu 24.04

# 安装依赖
apt update
apt install curl gnupg2 ca-certificates lsb-release ubuntu-keyring -y

# 添加Nginx官方GPG密钥
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
&nbsp; &nbsp; | tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null

# 添加仓库
echo&nbsp;"deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/ubuntu `lsb_release -cs` nginx"&nbsp;\
&nbsp; &nbsp; | tee /etc/apt/sources.list.d/nginx.list

# 安装
apt update
apt install nginx -y

# 启动
systemctl start nginx
systemctl&nbsp;enable&nbsp;nginx

2.1.2 准备后端服务

这里用一个简单的Python HTTP服务来模拟后端,方便看到请求分发到了哪台机器:

#!/usr/bin/env python3
# backend_server.py
import&nbsp;http.server
import&nbsp;socketserver
import&nbsp;socket

PORT =&nbsp;8080
HOSTNAME = socket.gethostname()
IP = socket.gethostbyname(HOSTNAME)

class&nbsp;MyHandler(http.server.SimpleHTTPRequestHandler):
&nbsp; &nbsp;&nbsp;def&nbsp;do_GET(self):
&nbsp; &nbsp; &nbsp; &nbsp; self.send_response(200)
&nbsp; &nbsp; &nbsp; &nbsp; self.send_header('Content-type',&nbsp;'text/html')
&nbsp; &nbsp; &nbsp; &nbsp; self.end_headers()
&nbsp; &nbsp; &nbsp; &nbsp; response =&nbsp;f"""
&nbsp; &nbsp; &nbsp; &nbsp; <html>
&nbsp; &nbsp; &nbsp; &nbsp; <body>
&nbsp; &nbsp; &nbsp; &nbsp; <h1>Hello from Backend Server</h1>
&nbsp; &nbsp; &nbsp; &nbsp; <p>Hostname:&nbsp;{HOSTNAME}</p>
&nbsp; &nbsp; &nbsp; &nbsp; <p>IP:&nbsp;{IP}</p>
&nbsp; &nbsp; &nbsp; &nbsp; <p>Port:&nbsp;{PORT}</p>
&nbsp; &nbsp; &nbsp; &nbsp; <p>Request Path:&nbsp;{self.path}</p>
&nbsp; &nbsp; &nbsp; &nbsp; </body>
&nbsp; &nbsp; &nbsp; &nbsp; </html>
&nbsp; &nbsp; &nbsp; &nbsp; """
&nbsp; &nbsp; &nbsp; &nbsp; self.wfile.write(response.encode())

with&nbsp;socketserver.TCPServer(("", PORT), MyHandler)&nbsp;as&nbsp;httpd:
&nbsp; &nbsp; print(f"Serving on port&nbsp;{PORT}")
&nbsp; &nbsp; httpd.serve_forever()

在三台后端服务器上分别启动:

python3 backend_server.py

或者如果你有Tomcat环境,直接用Tomcat也行:

# 修改不同服务器的端口,便于区分
# server.xml中修改HTTP Connector端口
# 分别启动三台Tomcat

2.2 核心配置

2.2.1 最简单的反向代理

先从最简单的配置开始,让Nginx把请求转发到后端服务:

# /etc/nginx/conf.d/proxy.conf
server {
&nbsp; &nbsp; listen 80;
&nbsp; &nbsp; server_name example.com;

&nbsp; &nbsp; location / {
&nbsp; &nbsp; &nbsp; &nbsp; proxy_pass http://192.168.1.11:8080;
&nbsp; &nbsp; }
}

测试一下:

curl http://192.168.1.10

你会看到返回的是后端服务器的响应。这就是最基础的反向代理,就这么简单。

2.2.2 完善的反向代理配置

实际生产中,光一个proxy_pass肯定不够。下面是生产环境必须配置的参数:

server {
&nbsp; &nbsp; listen 80;
&nbsp; &nbsp; server_name example.com;

&nbsp; &nbsp; location / {
&nbsp; &nbsp; &nbsp; &nbsp; proxy_pass http://192.168.1.11:8080;

&nbsp; &nbsp; &nbsp; &nbsp; # 代理头设置(重要!)
&nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header Host $host;
&nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header X-Real-IP $remote_addr;
&nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
&nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header X-Forwarded-Proto $scheme;

&nbsp; &nbsp; &nbsp; &nbsp; # 超时设置
&nbsp; &nbsp; &nbsp; &nbsp; proxy_connect_timeout 60s;
&nbsp; &nbsp; &nbsp; &nbsp; proxy_send_timeout 60s;
&nbsp; &nbsp; &nbsp; &nbsp; proxy_read_timeout 60s;

&nbsp; &nbsp; &nbsp; &nbsp; # 缓冲设置
&nbsp; &nbsp; &nbsp; &nbsp; proxy_buffering on;
&nbsp; &nbsp; &nbsp; &nbsp; proxy_buffer_size 4k;
&nbsp; &nbsp; &nbsp; &nbsp; proxy_buffers 8 32k;
&nbsp; &nbsp; &nbsp; &nbsp; proxy_busy_buffers_size 64k;
&nbsp; &nbsp; }
}

几个关键配置解释

  • proxy_set_header Host $host:把客户端请求的Host头传给后端。不设置这个,后端收到的Host是upstream的地址,很多应用会出问题。
  • X-Real-IP 和 X-Forwarded-For:让后端知道真实的客户端IP。不设置的话,后端看到的都是Nginx的IP。
  • proxy_buffering:开启缓冲后,Nginx会先把后端响应存到缓冲区,再发给客户端。这样即使客户端网速慢,也不会一直占用后端连接。

踩坑记录:有次我们的后端应用一直获取不到客户端真实IP,日志里全是Nginx的内网IP。排查半天,发现是忘了配X-Forwarded-For头。后端应用也需要配置信任代理地址才能正确解析这个头。

2.2.3 基础负载均衡

现在来配置负载均衡,把请求分发到多台后端服务器:

# /etc/nginx/conf.d/loadbalance.conf

# 定义后端服务器组
upstream backend_pool {
&nbsp; &nbsp; server 192.168.1.11:8080;
&nbsp; &nbsp; server 192.168.1.12:8080;
&nbsp; &nbsp; server 192.168.1.13:8080;
}

server {
&nbsp; &nbsp; listen 80;
&nbsp; &nbsp; server_name example.com;

&nbsp; &nbsp; location / {
&nbsp; &nbsp; &nbsp; &nbsp; proxy_pass http://backend_pool;

&nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header Host $host;
&nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header X-Real-IP $remote_addr;
&nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
&nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header X-Forwarded-Proto $scheme;
&nbsp; &nbsp; }
}

测试负载均衡效果:

# 连续发送多个请求,观察响应中的服务器IP变化
for&nbsp;i&nbsp;in&nbsp;{1..10};&nbsp;do
&nbsp; &nbsp; curl -s http://192.168.1.10 | grep&nbsp;"IP:"
done

你会看到请求被轮流分发到三台服务器上,这就是默认的轮询(Round Robin)算法。

2.2.4 负载均衡算法详解

Nginx支持多种负载均衡算法,选择合适的算法对系统性能影响很大。

1. 轮询(Round Robin)- 默认

upstream backend_pool {
&nbsp; &nbsp; server 192.168.1.11:8080;
&nbsp; &nbsp; server 192.168.1.12:8080;
&nbsp; &nbsp; server 192.168.1.13:8080;
}

最简单粗暴的算法,按顺序把请求分给每台服务器。适合后端服务器配置相同、无状态服务的场景。

2. 加权轮询(Weighted Round Robin)

upstream backend_pool {
&nbsp; &nbsp; server 192.168.1.11:8080 weight=5; &nbsp;# 处理50%的请求
&nbsp; &nbsp; server 192.168.1.12:8080 weight=3; &nbsp;# 处理30%的请求
&nbsp; &nbsp; server 192.168.1.13:8080 weight=2; &nbsp;# 处理20%的请求
}

服务器配置不同时使用。比如有台8核的机器和两台4核的,给8核的机器分配更多权重。

3. 最少连接数(Least Connections)

upstream backend_pool {
&nbsp; &nbsp; least_conn;
&nbsp; &nbsp; server 192.168.1.11:8080;
&nbsp; &nbsp; server 192.168.1.12:8080;
&nbsp; &nbsp; server 192.168.1.13:8080;
}

把请求分给当前连接数最少的服务器。适合请求处理时间不均匀的场景,比如有些请求1秒就处理完,有些要10秒。

实战经验:我们的API网关一开始用轮询,后来发现有些慢接口会导致某台服务器连接堆积。换成least_conn后,负载变得均匀多了。

4. IP哈希(IP Hash)

upstream backend_pool {
&nbsp; &nbsp; ip_hash;
&nbsp; &nbsp; server 192.168.1.11:8080;
&nbsp; &nbsp; server 192.168.1.12:8080;
&nbsp; &nbsp; server 192.168.1.13:8080;
}

根据客户端IP的哈希值分配服务器,同一个IP的请求总是落到同一台服务器。适合需要会话保持的场景。

注意:ip_hash有个坑,如果你前面还有一层代理(比如CDN),那所有请求的客户端IP都是CDN的IP,ip_hash就失效了。这时候需要用$http_x_forwarded_for来取真实IP。

5. 一致性哈希(Hash)

upstream backend_pool {
&nbsp; &nbsp; hash $request_uri consistent;
&nbsp; &nbsp; server 192.168.1.11:8080;
&nbsp; &nbsp; server 192.168.1.12:8080;
&nbsp; &nbsp; server 192.168.1.13:8080;
}

根据指定的key进行哈希。consistent参数启用一致性哈希,当服务器增减时,只有少部分请求会重新映射。

常用的hash key:

  • $request_uri:相同URL总是落到同一台服务器,适合缓存场景
  • $arg_userid:按用户ID分流
  • $cookie_sessionid:按session分流

6. 随机(Random)

upstream backend_pool {
&nbsp; &nbsp; random two least_conn;
&nbsp; &nbsp; server 192.168.1.11:8080;
&nbsp; &nbsp; server 192.168.1.12:8080;
&nbsp; &nbsp; server 192.168.1.13:8080;
}

随机选择两台服务器,然后从中选连接数少的那台。这个算法在Nginx 1.15.1引入,据官方说在大规模集群中效果比least_conn更好。

2.2.5 健康检查配置

负载均衡必须配合健康检查,不然一台服务器挂了,流量还往那儿发,用户体验就很差了。

被动健康检查(开源版Nginx):

upstream backend_pool {
&nbsp; &nbsp; server 192.168.1.11:8080 max_fails=3 fail_timeout=30s;
&nbsp; &nbsp; server 192.168.1.12:8080 max_fails=3 fail_timeout=30s;
&nbsp; &nbsp; server 192.168.1.13:8080 max_fails=3 fail_timeout=30s;
}

参数说明:

  • max_fails=3:连续3次请求失败就认为服务器挂了
  • fail_timeout=30s:服务器被标记为不可用的时间,30秒后会再次尝试

问题:被动检查有延迟,要等真实流量失败才能发现问题。而且恢复后也是立即全量切入,可能导致瞬间压力过大。

主动健康检查(Nginx Plus或第三方模块):

如果你用的是开源版Nginx,可以安装nginx_upstream_check_module模块:

upstream backend_pool {
&nbsp; &nbsp; server 192.168.1.11:8080;
&nbsp; &nbsp; server 192.168.1.12:8080;
&nbsp; &nbsp; server 192.168.1.13:8080;

&nbsp; &nbsp; # 主动健康检查配置
&nbsp; &nbsp; check interval=3000 rise=2 fall=3 timeout=2000 type=http;
&nbsp; &nbsp; check_http_send "GET /health HTTP/1.0\r\n\r\n";
&nbsp; &nbsp; check_http_expect_alive http_2xx http_3xx;
}

server {
&nbsp; &nbsp; # 健康检查状态页面
&nbsp; &nbsp; location /upstream_status {
&nbsp; &nbsp; &nbsp; &nbsp; check_status;
&nbsp; &nbsp; &nbsp; &nbsp; access_log off;
&nbsp; &nbsp; &nbsp; &nbsp; allow 192.168.1.0/24;
&nbsp; &nbsp; &nbsp; &nbsp; deny all;
&nbsp; &nbsp; }
}

参数说明:

  • interval=3000:每3秒检查一次
  • rise=2:连续2次成功认为恢复
  • fall=3:连续3次失败认为宕机
  • type=http:使用HTTP检查

2.2.6 后备服务器配置

upstream backend_pool {
&nbsp; &nbsp; server 192.168.1.11:8080;
&nbsp; &nbsp; server 192.168.1.12:8080;
&nbsp; &nbsp; server 192.168.1.13:8080 backup; &nbsp;# 备用服务器
&nbsp; &nbsp; server 192.168.1.14:8080 down; &nbsp; &nbsp;# 标记为下线,不接收流量
}
  • backup:备用服务器,只有当所有主服务器都不可用时才启用
  • down:标记服务器为下线状态,通常用于维护

2.2.7 连接复用配置

每次代理请求都新建TCP连接太浪费了,配置keepalive可以复用连接:

upstream backend_pool {
&nbsp; &nbsp; server 192.168.1.11:8080;
&nbsp; &nbsp; server 192.168.1.12:8080;
&nbsp; &nbsp; server 192.168.1.13:8080;

&nbsp; &nbsp; # 每个worker保持的空闲连接数
&nbsp; &nbsp; keepalive 100;

&nbsp; &nbsp; # 单个连接最大请求数
&nbsp; &nbsp; keepalive_requests 1000;

&nbsp; &nbsp; # 连接空闲超时
&nbsp; &nbsp; keepalive_timeout 60s;
}

server {
&nbsp; &nbsp; location / {
&nbsp; &nbsp; &nbsp; &nbsp; proxy_pass http://backend_pool;

&nbsp; &nbsp; &nbsp; &nbsp; # 必须!使用HTTP/1.1和清空Connection头
&nbsp; &nbsp; &nbsp; &nbsp; proxy_http_version 1.1;
&nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header Connection "";
&nbsp; &nbsp; }
}

这两行配置很容易漏掉

proxy_http_version 1.1;
proxy_set_header Connection "";

不加这两行,keepalive就不生效。因为HTTP/1.0默认是短连接,而且Nginx默认会把Connection头设成close。

2.3 启动和验证

2.3.1 配置验证

# 检查配置语法
nginx -t

# 输出示例
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful

2.3.2 重载配置

# 平滑重载,不中断服务
nginx -s reload

# 或者使用systemd
systemctl reload nginx

2.3.3 验证负载均衡

# 方法1:多次curl观察响应
for&nbsp;i&nbsp;in&nbsp;{1..10};&nbsp;do
&nbsp; &nbsp; curl -s http://192.168.1.10 | grep&nbsp;"IP:"
&nbsp; &nbsp; sleep 0.5
done

# 方法2:使用ab压测
ab -n 1000 -c 100 http://192.168.1.10/

# 方法3:查看后端服务器访问日志
tail -f /var/log/nginx/access.log

三、示例代码和配置

3.1 完整配置示例

这是一个生产级的反向代理+负载均衡配置:

# /etc/nginx/nginx.conf

user nginx;
worker_processes auto;
worker_rlimit_nofile 65535;

error_log /var/log/nginx/error.log warn;
pid /run/nginx.pid;

events {
&nbsp; &nbsp; worker_connections 65535;
&nbsp; &nbsp; use epoll;
&nbsp; &nbsp; multi_accept on;
}

http {
&nbsp; &nbsp; include /etc/nginx/mime.types;
&nbsp; &nbsp; default_type application/octet-stream;

&nbsp; &nbsp; # 日志格式
&nbsp; &nbsp; log_format main '$remote_addr - $remote_user [$time_local] "$request" '
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '$status $body_bytes_sent "$http_referer" '
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; '"$http_user_agent" "$http_x_forwarded_for" '
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'rt=$request_time uct="$upstream_connect_time" '
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'uht="$upstream_header_time" urt="$upstream_response_time"';

&nbsp; &nbsp; access_log /var/log/nginx/access.log main;

&nbsp; &nbsp; sendfile on;
&nbsp; &nbsp; tcp_nopush on;
&nbsp; &nbsp; tcp_nodelay on;

&nbsp; &nbsp; keepalive_timeout 65;
&nbsp; &nbsp; keepalive_requests 10000;

&nbsp; &nbsp; # Gzip压缩
&nbsp; &nbsp; gzip on;
&nbsp; &nbsp; gzip_vary on;
&nbsp; &nbsp; gzip_min_length 1024;
&nbsp; &nbsp; gzip_types text/plain text/css application/json application/javascript;

&nbsp; &nbsp; # 上游服务器组
&nbsp; &nbsp; upstream api_servers {
&nbsp; &nbsp; &nbsp; &nbsp; least_conn;

&nbsp; &nbsp; &nbsp; &nbsp; server 192.168.1.11:8080 weight=3 max_fails=3 fail_timeout=30s;
&nbsp; &nbsp; &nbsp; &nbsp; server 192.168.1.12:8080 weight=3 max_fails=3 fail_timeout=30s;
&nbsp; &nbsp; &nbsp; &nbsp; server 192.168.1.13:8080 weight=2 max_fails=3 fail_timeout=30s;
&nbsp; &nbsp; &nbsp; &nbsp; server 192.168.1.14:8080 backup;

&nbsp; &nbsp; &nbsp; &nbsp; keepalive 300;
&nbsp; &nbsp; &nbsp; &nbsp; keepalive_requests 10000;
&nbsp; &nbsp; &nbsp; &nbsp; keepalive_timeout 60s;
&nbsp; &nbsp; }

&nbsp; &nbsp; # 静态资源服务器组
&nbsp; &nbsp; upstream static_servers {
&nbsp; &nbsp; &nbsp; &nbsp; server 192.168.1.21:80;
&nbsp; &nbsp; &nbsp; &nbsp; server 192.168.1.22:80;

&nbsp; &nbsp; &nbsp; &nbsp; keepalive 100;
&nbsp; &nbsp; }

&nbsp; &nbsp; # 限流配置
&nbsp; &nbsp; limit_req_zone $binary_remote_addr zone=api_limit:10m rate=100r/s;
&nbsp; &nbsp; limit_conn_zone $binary_remote_addr zone=conn_limit:10m;

&nbsp; &nbsp; # 主站配置
&nbsp; &nbsp; server {
&nbsp; &nbsp; &nbsp; &nbsp; listen 80;
&nbsp; &nbsp; &nbsp; &nbsp; server_name example.com www.example.com;
&nbsp; &nbsp; &nbsp; &nbsp; return 301 https://$server_name$request_uri;
&nbsp; &nbsp; }

&nbsp; &nbsp; server {
&nbsp; &nbsp; &nbsp; &nbsp; listen 443 ssl;
&nbsp; &nbsp; &nbsp; &nbsp; http2 on;
&nbsp; &nbsp; &nbsp; &nbsp; server_name example.com www.example.com;

&nbsp; &nbsp; &nbsp; &nbsp; ssl_certificate /etc/nginx/ssl/example.com.crt;
&nbsp; &nbsp; &nbsp; &nbsp; ssl_certificate_key /etc/nginx/ssl/example.com.key;
&nbsp; &nbsp; &nbsp; &nbsp; ssl_session_cache shared:SSL:10m;
&nbsp; &nbsp; &nbsp; &nbsp; ssl_session_timeout 1d;
&nbsp; &nbsp; &nbsp; &nbsp; ssl_protocols TLSv1.2 TLSv1.3;

&nbsp; &nbsp; &nbsp; &nbsp; # 安全头
&nbsp; &nbsp; &nbsp; &nbsp; add_header X-Frame-Options "SAMEORIGIN" always;
&nbsp; &nbsp; &nbsp; &nbsp; add_header X-Content-Type-Options "nosniff" always;
&nbsp; &nbsp; &nbsp; &nbsp; add_header X-XSS-Protection "1; mode=block" always;

&nbsp; &nbsp; &nbsp; &nbsp; # API接口
&nbsp; &nbsp; &nbsp; &nbsp; location /api/ {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; limit_req zone=api_limit burst=50 nodelay;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; limit_conn conn_limit 20;

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; proxy_pass http://api_servers;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; proxy_http_version 1.1;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header Connection "";
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header Host $host;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header X-Real-IP $remote_addr;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header X-Forwarded-Proto $scheme;

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; proxy_connect_timeout 10s;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; proxy_send_timeout 60s;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; proxy_read_timeout 60s;

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; proxy_next_upstream error timeout http_502 http_503 http_504;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; proxy_next_upstream_tries 3;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; proxy_next_upstream_timeout 30s;
&nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; # 静态资源
&nbsp; &nbsp; &nbsp; &nbsp; location /static/ {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; proxy_pass http://static_servers;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; proxy_http_version 1.1;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header Connection "";

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; proxy_cache_valid 200 1d;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; expires 30d;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; add_header Cache-Control "public, immutable";
&nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; # WebSocket代理
&nbsp; &nbsp; &nbsp; &nbsp; location /ws/ {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; proxy_pass http://api_servers;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; proxy_http_version 1.1;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header Upgrade $http_upgrade;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header Connection "upgrade";
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header Host $host;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; proxy_read_timeout 86400s;
&nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; # 健康检查接口
&nbsp; &nbsp; &nbsp; &nbsp; location /health {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; access_log off;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return 200 'OK';
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; add_header Content-Type text/plain;
&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; }

&nbsp; &nbsp; # 内部状态监控
&nbsp; &nbsp; server {
&nbsp; &nbsp; &nbsp; &nbsp; listen 127.0.0.1:8080;

&nbsp; &nbsp; &nbsp; &nbsp; location /nginx_status {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; stub_status on;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; access_log off;
&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; }
}

3.2 实际应用案例

案例1:电商网站高可用架构

背景:日均PV 1000万,需要支持大促期间10倍流量峰值

架构设计:

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;┌─────────────────┐
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; CDN层 &nbsp; &nbsp; &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp;静态资源加速 &nbsp; &nbsp;│
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;└────────┬────────┘
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;┌────────▼────────┐
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; SLB/CLB层 &nbsp; &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp;云负载均衡器 &nbsp; &nbsp;│
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;└────────┬────────┘
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ┌───────────────────┼───────────────────┐
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp;┌──────▼──────┐ &nbsp; &nbsp; ┌──────▼──────┐ &nbsp; &nbsp; ┌──────▼──────┐
&nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp;Nginx 01 &nbsp; │ &nbsp; &nbsp; │ &nbsp;Nginx 02 &nbsp; │ &nbsp; &nbsp; │ &nbsp;Nginx 03 &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp;│ 反向代理集群 │ &nbsp; &nbsp; │ 反向代理集群 │ &nbsp; &nbsp; │ 反向代理集群 │
&nbsp; &nbsp; &nbsp; &nbsp;└──────┬──────┘ &nbsp; &nbsp; └──────┬──────┘ &nbsp; &nbsp; └──────┬──────┘
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; └───────────────────┼───────────────────┘
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp;┌──────────────────────────┼──────────────────────────┐
&nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│
&nbsp; &nbsp; &nbsp; &nbsp;▼ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ▼ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;▼
&nbsp; ┌─────────┐ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;┌─────────┐ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ┌─────────┐
&nbsp; │ API集群 │ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ Web集群 │ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ 静态资源 │
&nbsp; │ 商品/订单│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;│ 前端渲染 │ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ 图片/CSS │
&nbsp; └─────────┘ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;└─────────┘ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; └─────────┘

Nginx配置:

# 商品服务
upstream product_service {
&nbsp; &nbsp; least_conn;
&nbsp; &nbsp; server 10.0.1.1:8080 weight=3;
&nbsp; &nbsp; server 10.0.1.2:8080 weight=3;
&nbsp; &nbsp; server 10.0.1.3:8080 weight=2;
&nbsp; &nbsp; keepalive 200;
}

# 订单服务
upstream order_service {
&nbsp; &nbsp; least_conn;
&nbsp; &nbsp; server 10.0.2.1:8080 weight=3;
&nbsp; &nbsp; server 10.0.2.2:8080 weight=3;
&nbsp; &nbsp; server 10.0.2.3:8080 weight=2;
&nbsp; &nbsp; keepalive 200;
}

# 用户服务
upstream user_service {
&nbsp; &nbsp; ip_hash; &nbsp;# 需要会话保持
&nbsp; &nbsp; server 10.0.3.1:8080;
&nbsp; &nbsp; server 10.0.3.2:8080;
&nbsp; &nbsp; server 10.0.3.3:8080;
&nbsp; &nbsp; keepalive 100;
}

server {
&nbsp; &nbsp; listen 80;
&nbsp; &nbsp; server_name api.shop.com;

&nbsp; &nbsp; # 商品接口
&nbsp; &nbsp; location /api/products {
&nbsp; &nbsp; &nbsp; &nbsp; proxy_pass http://product_service;
&nbsp; &nbsp; &nbsp; &nbsp; proxy_http_version 1.1;
&nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header Connection "";
&nbsp; &nbsp; &nbsp; &nbsp; # ... 其他代理配置
&nbsp; &nbsp; }

&nbsp; &nbsp; # 订单接口
&nbsp; &nbsp; location /api/orders {
&nbsp; &nbsp; &nbsp; &nbsp; proxy_pass http://order_service;
&nbsp; &nbsp; &nbsp; &nbsp; proxy_http_version 1.1;
&nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header Connection "";
&nbsp; &nbsp; &nbsp; &nbsp; # ... 其他代理配置
&nbsp; &nbsp; }

&nbsp; &nbsp; # 用户接口
&nbsp; &nbsp; location /api/users {
&nbsp; &nbsp; &nbsp; &nbsp; proxy_pass http://user_service;
&nbsp; &nbsp; &nbsp; &nbsp; proxy_http_version 1.1;
&nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header Connection "";
&nbsp; &nbsp; &nbsp; &nbsp; # ... 其他代理配置
&nbsp; &nbsp; }
}

案例2:灰度发布配置

背景:新版本上线,先让10%的用户访问新版本,验证没问题后逐步扩大比例

# 新旧版本服务器
upstream app_v1 {
&nbsp; &nbsp; server 10.0.1.1:8080;
&nbsp; &nbsp; server 10.0.1.2:8080;
&nbsp; &nbsp; keepalive 100;
}

upstream app_v2 {
&nbsp; &nbsp; server 10.0.2.1:8080;
&nbsp; &nbsp; server 10.0.2.2:8080;
&nbsp; &nbsp; keepalive 100;
}

# 方法1:基于权重的灰度
upstream app_canary {
&nbsp; &nbsp; server 10.0.1.1:8080 weight=9; &nbsp;# v1
&nbsp; &nbsp; server 10.0.1.2:8080 weight=9; &nbsp;# v1
&nbsp; &nbsp; server 10.0.2.1:8080 weight=1; &nbsp;# v2 (10%)
&nbsp; &nbsp; server 10.0.2.2:8080 weight=1; &nbsp;# v2 (10%)
&nbsp; &nbsp; keepalive 100;
}

# 方法2:基于Cookie的灰度
map $cookie_version $upstream_group {
&nbsp; &nbsp; default app_v1;
&nbsp; &nbsp; "v2" &nbsp; &nbsp;app_v2;
}

# 方法3:基于请求头的灰度
map $http_x_version $upstream_group_header {
&nbsp; &nbsp; default app_v1;
&nbsp; &nbsp; "v2" &nbsp; &nbsp;app_v2;
}

# 方法4:基于用户ID的灰度(取模)
split_clients $arg_userid $app_version {
&nbsp; &nbsp; 10% &nbsp;app_v2;
&nbsp; &nbsp; * &nbsp; &nbsp;app_v1;
}

server {
&nbsp; &nbsp; listen 80;
&nbsp; &nbsp; server_name app.example.com;

&nbsp; &nbsp; # 使用Cookie灰度
&nbsp; &nbsp; location / {
&nbsp; &nbsp; &nbsp; &nbsp; proxy_pass http://$upstream_group;
&nbsp; &nbsp; &nbsp; &nbsp; proxy_http_version 1.1;
&nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header Connection "";
&nbsp; &nbsp; }

&nbsp; &nbsp; # 设置灰度Cookie的接口
&nbsp; &nbsp; location /set_version {
&nbsp; &nbsp; &nbsp; &nbsp; add_header Set-Cookie "version=$arg_v; Path=/; Max-Age=86400";
&nbsp; &nbsp; &nbsp; &nbsp; return 200 "Version set to $arg_v";
&nbsp; &nbsp; }
}

灰度发布流程:

  1. 部署新版本服务到v2集群
  2. 配置10%流量到v2
  3. 监控v2的错误率、响应时间
  4. 逐步调整权重:10% -> 30% -> 50% -> 100%
  5. 下线v1集群

案例3:WebSocket负载均衡

背景:实时聊天应用,需要长连接支持

upstream ws_servers {
&nbsp; &nbsp; # WebSocket需要会话保持
&nbsp; &nbsp; ip_hash;
&nbsp; &nbsp; server 10.0.1.1:8080;
&nbsp; &nbsp; server 10.0.1.2:8080;
&nbsp; &nbsp; server 10.0.1.3:8080;

&nbsp; &nbsp; # WebSocket连接数较少,keepalive可以小一些
&nbsp; &nbsp; keepalive 50;
}

server {
&nbsp; &nbsp; listen 80;
&nbsp; &nbsp; server_name ws.example.com;

&nbsp; &nbsp; location / {
&nbsp; &nbsp; &nbsp; &nbsp; proxy_pass http://ws_servers;
&nbsp; &nbsp; &nbsp; &nbsp; proxy_http_version 1.1;

&nbsp; &nbsp; &nbsp; &nbsp; # WebSocket必须的头
&nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header Upgrade $http_upgrade;
&nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header Connection "upgrade";

&nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header Host $host;
&nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header X-Real-IP $remote_addr;
&nbsp; &nbsp; &nbsp; &nbsp; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

&nbsp; &nbsp; &nbsp; &nbsp; # WebSocket长连接超时设置
&nbsp; &nbsp; &nbsp; &nbsp; proxy_read_timeout 86400s;
&nbsp; &nbsp; &nbsp; &nbsp; proxy_send_timeout 86400s;

&nbsp; &nbsp; &nbsp; &nbsp; # 禁用缓冲
&nbsp; &nbsp; &nbsp; &nbsp; proxy_buffering off;
&nbsp; &nbsp; }
}

踩坑记录:WebSocket一开始配了least_conn,结果用户聊着聊着就断线了。排查发现是连接被分到了不同的服务器。WebSocket必须用ip_hash或者sticky session保证会话保持。

四、最佳实践和注意事项

4.1 最佳实践

1. 分层部署架构

不要把所有服务都放在一个upstream里,按业务功能分组:

# 好的做法
upstream user_api { ... }
upstream order_api { ... }
upstream product_api { ... }

# 不好的做法
upstream all_api {
&nbsp; &nbsp; server user1:8080;
&nbsp; &nbsp; server user2:8080;
&nbsp; &nbsp; server order1:8080; &nbsp;# 混在一起
&nbsp; &nbsp; server product1:8080; &nbsp;# 难以管理
}

2. 合理的超时设置

不同类型的请求设置不同的超时:

# 短请求(列表查询)
location /api/list {
&nbsp; &nbsp; proxy_read_timeout 10s;
}

# 长请求(报表导出)
location /api/export {
&nbsp; &nbsp; proxy_read_timeout 300s;
}

# 文件上传
location /api/upload {
&nbsp; &nbsp; client_max_body_size 500m;
&nbsp; &nbsp; proxy_read_timeout 600s;
}

3. 错误页面友好展示

# 自定义错误页面
error_page 502 503 504 /50x.html;
location = /50x.html {
&nbsp; &nbsp; root /usr/share/nginx/html;
&nbsp; &nbsp; internal;
}

# 或者返回JSON
error_page 502 503 504 = @fallback;
location @fallback {
&nbsp; &nbsp; default_type application/json;
&nbsp; &nbsp; return 503 '{"code": 503, "message": "Service temporarily unavailable"}';
}

4. 监控指标收集

日志中记录upstream响应时间,便于分析:

log_format upstream_log '$remote_addr [$time_local] '
&nbsp; &nbsp; '$request $status '
&nbsp; &nbsp; 'upstream: $upstream_addr '
&nbsp; &nbsp; 'response_time: $upstream_response_time '
&nbsp; &nbsp; 'connect_time: $upstream_connect_time';

5. 平滑扩缩容

新增服务器时,先设置低权重,逐步提升:

upstream backend {
&nbsp; &nbsp; server 10.0.1.1:8080 weight=10;
&nbsp; &nbsp; server 10.0.1.2:8080 weight=10;
&nbsp; &nbsp; server 10.0.1.3:8080 weight=1; &nbsp;# 新机器,先低权重
}

4.2 注意事项

| 常见错误 | 原因分析 | 解决方案 | | — | — | — | | 502 Bad Gateway | 后端服务未启动或连接被拒绝 | 检查后端服务状态,确认端口正确 | | 504 Gateway Timeout | 后端响应超时 | 增加proxy_read_timeout,或优化后端性能 | | upstream无法连接 | 网络不通或防火墙阻止 | 检查网络连通性,开放防火墙端口 | | keepalive不生效 | 缺少必要配置 | 添加proxy_http_version 1.1和Connection “” | | 负载不均衡 | 算法选择不当或权重配置问题 | 根据场景选择合适算法,检查权重配置 | | 会话丢失 | 无状态轮询导致请求分发到不同服务器 | 使用ip_hash或sticky session | | 健康检查延迟 | 被动检查需要真实流量触发 | 配置主动健康检查模块 | | X-Forwarded-For链过长 | 多层代理重复追加 | 在入口处设置X-Forwarded-For为$remote_addr |

五、故障排查和监控

5.1 故障排查

5.1.1 常见故障诊断流程

502错误排查

# 1. 检查后端服务是否运行
curl -I http://backend_ip:port/health

# 2. 检查Nginx到后端的网络连通性
telnet backend_ip port

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

# 4. 检查后端服务日志
# 看是否收到请求,是否有报错

# 5. 检查连接数是否达到限制
ss -s
cat /proc/sys/net/core/somaxconn

504超时排查

# 1. 测试后端接口响应时间
time curl http://backend_ip:port/api/slow

# 2. 检查Nginx超时配置
nginx -T | grep -E&nbsp;"proxy_.*_timeout"

# 3. 分析慢请求日志
awk&nbsp;'$NF > 5'&nbsp;/var/log/nginx/access.log &nbsp;# 响应时间>5秒的请求

负载不均排查

# 1. 统计各后端服务器请求量
awk&nbsp;'{print $NF}'&nbsp;/var/log/nginx/access.log | sort | uniq -c | sort -rn

# 2. 检查upstream配置
nginx -T | grep -A 20&nbsp;"upstream"

# 3. 检查是否有服务器被标记为不可用
# 查看error.log中的upstream相关错误

5.1.2 调试配置

临时开启详细日志排查问题:

# 临时配置,排查完记得关掉
error_log /var/log/nginx/error.log debug;

# 或者只对特定请求开启debug
location /api/problem {
&nbsp; &nbsp; error_log /var/log/nginx/debug.log debug;
&nbsp; &nbsp; proxy_pass http://backend;
}

5.2 性能监控

5.2.1 内置状态监控

server {
&nbsp; &nbsp; listen 127.0.0.1:8080;

&nbsp; &nbsp; location /nginx_status {
&nbsp; &nbsp; &nbsp; &nbsp; stub_status on;
&nbsp; &nbsp; &nbsp; &nbsp; access_log off;
&nbsp; &nbsp; &nbsp; &nbsp; allow 127.0.0.1;
&nbsp; &nbsp; &nbsp; &nbsp; deny all;
&nbsp; &nbsp; }
}

获取状态:

curl http://127.0.0.1:8080/nginx_status

# 输出示例:
# Active connections: 234
# server accepts handled requests
# &nbsp;12847932 12847932 98234756
# Reading: 5 Writing: 67 Waiting: 162

指标说明:

  • Active connections:当前活跃连接数
  • accepts:已接受的连接总数
  • handled:已处理的连接总数(应该等于accepts,不等说明有连接被丢弃)
  • requests:已处理的请求总数
  • Reading:正在读取请求头的连接数
  • Writing:正在发送响应的连接数
  • Waiting:Keep-alive空闲连接数

5.2.2 Prometheus监控集成

使用nginx-prometheus-exporter:

# 安装exporter
docker run -d -p 9113:9113 \
&nbsp; &nbsp; nginx/nginx-prometheus-exporter:latest \
&nbsp; &nbsp; -nginx.scrape-uri=http://nginx:8080/nginx_status

Prometheus配置:

scrape_configs:
&nbsp;&nbsp;-&nbsp;job_name:&nbsp;'nginx'
&nbsp; &nbsp;&nbsp;static_configs:
&nbsp; &nbsp; &nbsp;&nbsp;-&nbsp;targets:&nbsp;['localhost:9113']

关键告警规则:

groups:
&nbsp;&nbsp;-&nbsp;name:&nbsp;nginx_alerts
&nbsp; &nbsp;&nbsp;rules:
&nbsp; &nbsp; &nbsp;&nbsp;-&nbsp;alert:&nbsp;NginxHighConnectionUsage
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;expr:&nbsp;nginx_connections_active&nbsp;/&nbsp;nginx_connections_accepted&nbsp;>&nbsp;0.8
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for:&nbsp;5m
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;labels:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;severity:&nbsp;warning
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;annotations:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;summary:&nbsp;"Nginx连接使用率过高"

&nbsp; &nbsp; &nbsp;&nbsp;-&nbsp;alert:&nbsp;NginxHighErrorRate
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;expr:&nbsp;rate(nginx_http_requests_total{status=~"5.."}[5m])&nbsp;/&nbsp;rate(nginx_http_requests_total[5m])&nbsp;>&nbsp;0.01
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for:&nbsp;5m
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;labels:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;severity:&nbsp;critical
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;annotations:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;summary:&nbsp;"Nginx 5xx错误率超过1%"

5.3 备份与恢复

5.3.1 配置备份

#!/bin/bash
# /usr/local/bin/backup_nginx.sh

BACKUP_DIR="/data/backup/nginx"
DATE=$(date +%Y%m%d_%H%M%S)
NGINX_DIR="/etc/nginx"

# 创建备份目录
mkdir -p&nbsp;${BACKUP_DIR}

# 备份配置文件
tar -czf&nbsp;${BACKUP_DIR}/nginx_config_${DATE}.tar.gz&nbsp;${NGINX_DIR}

# 备份SSL证书
tar -czf&nbsp;${BACKUP_DIR}/nginx_ssl_${DATE}.tar.gz&nbsp;${NGINX_DIR}/ssl/

# 保留30天备份
find&nbsp;${BACKUP_DIR}&nbsp;-name&nbsp;"*.tar.gz"&nbsp;-mtime +30 -delete

echo&nbsp;"Backup completed:&nbsp;${BACKUP_DIR}/nginx_config_${DATE}.tar.gz"

5.3.2 配置恢复

#!/bin/bash
# 恢复配置

BACKUP_FILE=$1

if&nbsp;[ -z&nbsp;"$BACKUP_FILE"&nbsp;];&nbsp;then
&nbsp; &nbsp;&nbsp;echo&nbsp;"Usage:&nbsp;$0&nbsp;<backup_file>"
&nbsp; &nbsp;&nbsp;exit&nbsp;1
fi

# 备份当前配置
mv /etc/nginx /etc/nginx.bak.$(date +%s)

# 解压恢复
tar -xzf&nbsp;$BACKUP_FILE&nbsp;-C /

# 测试配置
nginx -t

if&nbsp;[ $? -eq 0 ];&nbsp;then
&nbsp; &nbsp; nginx -s reload
&nbsp; &nbsp;&nbsp;echo&nbsp;"Configuration restored successfully"
else
&nbsp; &nbsp;&nbsp;echo&nbsp;"Configuration test failed, rolling back"
&nbsp; &nbsp; rm -rf /etc/nginx
&nbsp; &nbsp; mv /etc/nginx.bak.* /etc/nginx
fi

六、总结

6.1 技术要点回顾

反向代理和负载均衡是Nginx最核心的功能,掌握好这两个技能,基本就能应对大部分Web架构需求了。

反向代理要点

  • proxy_pass指令是核心
  • 代理头设置影响后端获取真实信息
  • 缓冲区配置影响内存使用和响应速度
  • 超时配置要根据业务调整

负载均衡要点

  • 算法选择:无状态服务用least_conn,需要会话保持用ip_hash
  • 健康检查:生产环境必须配置max_fails和fail_timeout
  • 连接复用:keepalive可以显著提升性能
  • 故障转移:proxy_next_upstream配置自动重试

6.2 进阶学习方向

  1. Nginx Plus:商业版功能,主动健康检查、动态配置、更好的监控
  2. OpenResty:整合Lua,实现复杂的业务逻辑
  3. Envoy:云原生时代的新选择,功能更强大
  4. 服务网格:Istio、Linkerd等,下一代流量管理方案

6.3 参考资料

  • Nginx官方文档 – ngx_http_upstream_module: https://nginx.org/en/docs/http/ngx_http_upstream_module.html
  • Nginx官方文档 – ngx_http_proxy_module: https://nginx.org/en/docs/http/ngx_http_proxy_module.html
  • Nginx负载均衡指南: https://docs.nginx.com/nginx/admin-guide/load-balancer/

附录

A. 命令速查表

| 命令 | 说明 | | — | — | | nginx -t | 测试配置语法 | | nginx -s reload | 平滑重载配置 | | nginx -T | 输出完整配置 | | curl -I http://url | 查看响应头 | | ss -tlnp | 查看监听端口 | | ss -ant | grep ESTAB | 查看已建立的连接 |

B. 配置参数详解

| 参数 | 上下文 | 默认值 | 说明 | | — | — | — | — | | proxy_pass | location | – | 代理目标地址 | | proxy_connect_timeout | http,server,location | 60s | 连接超时 | | proxy_send_timeout | http,server,location | 60s | 发送超时 | | proxy_read_timeout | http,server,location | 60s | 读取超时 | | proxy_next_upstream | http,server,location | error timeout | 触发重试的条件 | | keepalive | upstream | – | 保持的空闲连接数 | | weight | server | 1 | 服务器权重 | | max_fails | server | 1 | 最大失败次数 | | fail_timeout | server | 10s | 失败超时时间 |

C. 术语表

| 术语 | 解释 | | — | — | | 反向代理 | 代理服务端,客户端不知道真实服务器地址 | | 正向代理 | 代理客户端,服务端不知道真实客户端地址 | | 负载均衡 | 将请求分发到多台服务器 | | Upstream | Nginx中定义后端服务器组的指令 | | 健康检查 | 检测后端服务器是否可用 | | 会话保持 | 同一用户的请求总是发到同一台服务器 | | 灰度发布 | 逐步将流量切换到新版本 | | 熔断 | 当后端不可用时自动停止转发请求 |


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:马哥网络安全 点击关注 👉 点击关注 👉《Nginx反向代理+负载均衡实战:小白也能搭建高可用架构》

评论:0   参与:  0