0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Nginx反向代理和负载均衡配置实战

马哥Linux运维 来源:马哥Linux运维 2026-01-23 13:44 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

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

实验环境架构

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

二、详细步骤

2.1 准备工作

2.1.1 安装Nginx

Rocky Linux 9

# 添加Nginx官方仓库
cat > /etc/yum.repos.d/nginx.repo << '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 enable 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 
  | tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null

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

# 安装
apt update
apt install nginx -y

# 启动
systemctl start nginx
systemctlenablenginx

2.1.2 准备后端服务

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

#!/usr/bin/env python3
# backend_server.py
importhttp.server
importsocketserver
importsocket

PORT =8080
HOSTNAME = socket.gethostname()
IP = socket.gethostbyname(HOSTNAME)

classMyHandler(http.server.SimpleHTTPRequestHandler):
 defdo_GET(self):
    self.send_response(200)
    self.send_header('Content-type','text/html')
    self.end_headers()
    response =f"""
    
    
    

Hello from Backend Server

Hostname:{HOSTNAME}

IP:{IP}

Port:{PORT}

Request Path:{self.path}

""" self.wfile.write(response.encode()) withsocketserver.TCPServer(("", PORT), MyHandler)ashttpd: print(f"Serving on port{PORT}") 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 {
  listen 80;
  server_name example.com;

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

测试一下:

curl http://192.168.1.10

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

2.2.2 完善的反向代理配置

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

server {
  listen 80;
  server_name example.com;

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

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

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

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

几个关键配置解释

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 {
  server 192.168.1.11:8080;
  server 192.168.1.12:8080;
  server 192.168.1.13:8080;
}

server {
  listen 80;
  server_name example.com;

  location / {
    proxy_pass http://backend_pool;

    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;
  }
}

测试负载均衡效果:

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

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

2.2.4 负载均衡算法详解

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

1. 轮询(Round Robin)- 默认

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

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

2. 加权轮询(Weighted Round Robin)

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

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

3. 最少连接数(Least Connections)

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

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

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

4. IP哈希(IP Hash)

upstream backend_pool {
  ip_hash;
  server 192.168.1.11:8080;
  server 192.168.1.12:8080;
  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 {
  hash $request_uri consistent;
  server 192.168.1.11:8080;
  server 192.168.1.12:8080;
  server 192.168.1.13:8080;
}

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

常用的hash key:

$request_uri:相同URL总是落到同一台服务器,适合缓存场景

$arg_userid:按用户ID分流

$cookie_sessionid:按session分流

6. 随机(Random)

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

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

2.2.5 健康检查配置

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

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

upstream backend_pool {
  server 192.168.1.11:8080 max_fails=3 fail_timeout=30s;
  server 192.168.1.12:8080 max_fails=3 fail_timeout=30s;
  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 {
  server 192.168.1.11:8080;
  server 192.168.1.12:8080;
  server 192.168.1.13:8080;

  # 主动健康检查配置
  check interval=3000 rise=2 fall=3 timeout=2000 type=http;
  check_http_send "GET /health HTTP/1.0

";
  check_http_expect_alive http_2xx http_3xx;
}

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

参数说明:

interval=3000:每3秒检查一次

rise=2:连续2次成功认为恢复

fall=3:连续3次失败认为宕机

type=http:使用HTTP检查

2.2.6 后备服务器配置

upstream backend_pool {
  server 192.168.1.11:8080;
  server 192.168.1.12:8080;
  server 192.168.1.13:8080 backup; # 备用服务器
  server 192.168.1.14:8080 down;  # 标记为下线,不接收流量
}

backup:备用服务器,只有当所有主服务器都不可用时才启用

down:标记服务器为下线状态,通常用于维护

2.2.7 连接复用配置

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

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

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

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

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

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

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

这两行配置很容易漏掉

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观察响应
foriin{1..10};do
  curl -s http://192.168.1.10 | grep"IP:"
  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 {
  worker_connections 65535;
  use epoll;
  multi_accept on;
}

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

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

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

  sendfile on;
  tcp_nopush on;
  tcp_nodelay on;

  keepalive_timeout 65;
  keepalive_requests 10000;

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

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

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

    keepalive 300;
    keepalive_requests 10000;
    keepalive_timeout 60s;
  }

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

    keepalive 100;
  }

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

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

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

    ssl_certificate /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;
    ssl_session_cache shared10m;
    ssl_session_timeout 1d;
    ssl_protocols TLSv1.2 TLSv1.3;

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

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

      proxy_pass http://api_servers;
      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;
      proxy_set_header X-Forwarded-Proto $scheme;

      proxy_connect_timeout 10s;
      proxy_send_timeout 60s;
      proxy_read_timeout 60s;

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

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

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

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

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

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

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

3.2 实际应用案例

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

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

架构设计:

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

Nginx配置:

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

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

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

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

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

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

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

案例2:灰度发布配置

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

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

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

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

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

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

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

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

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

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

灰度发布流程:

部署新版本服务到v2集群

配置10%流量到v2

监控v2的错误率、响应时间

逐步调整权重:10% -> 30% -> 50% -> 100%

下线v1集群

案例3:WebSocket负载均衡

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

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

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

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

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

    # WebSocket必须的头
    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 86400s;
    proxy_send_timeout 86400s;

    # 禁用缓冲
    proxy_buffering off;
  }
}

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

四、最佳实践和注意事项

4.1 最佳实践

1. 分层部署架构

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

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

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

2. 合理的超时设置

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

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

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

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

3. 错误页面友好展示

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

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

4. 监控指标收集

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

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

5. 平滑扩缩容

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

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

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"proxy_.*_timeout"

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

负载不均排查

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

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

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

5.1.2 调试配置

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

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

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

5.2 性能监控

5.2.1 内置状态监控

server {
  listen 127.0.0.1:8080;

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

获取状态:

curl http://127.0.0.1:8080/nginx_status

# 输出示例:
# Active connections: 234
# server accepts handled requests
# 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 
  nginx/nginx-prometheus-exporter:latest 
  -nginx.scrape-uri=http://nginx:8080/nginx_status

Prometheus配置:

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

关键告警规则:

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

  -alert:NginxHighErrorRate
   expr:rate(nginx_http_requests_total{status=~"5.."}[5m])/rate(nginx_http_requests_total[5m])>0.01
   for:5m
   labels:
    severity:critical
   annotations:
    summary:"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${BACKUP_DIR}

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

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

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

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

5.3.2 配置恢复

#!/bin/bash
# 恢复配置

BACKUP_FILE=$1

if[ -z"$BACKUP_FILE"];then
 echo"Usage:$0"
 exit1
fi

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

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

# 测试配置
nginx -t

if[ $? -eq 0 ];then
  nginx -s reload
 echo"Configuration restored successfully"
else
 echo"Configuration test failed, rolling back"
  rm -rf /etc/nginx
  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 进阶学习方向

Nginx Plus:商业版功能,主动健康检查、动态配置、更好的监控

OpenResty:整合Lua,实现复杂的业务逻辑

Envoy:云原生时代的新选择,功能更强大

服务网格: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中定义后端服务器组的指令
健康检查 检测后端服务器是否可用
会话保持 同一用户的请求总是发到同一台服务器
灰度发布 逐步将流量切换到新版本
熔断 当后端不可用时自动停止转发请求

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 服务器
    +关注

    关注

    14

    文章

    10440

    浏览量

    91851
  • 负载均衡
    +关注

    关注

    0

    文章

    137

    浏览量

    12918
  • nginx
    +关注

    关注

    0

    文章

    200

    浏览量

    13246

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

文章出处:【微信号:magedu-Linux,微信公众号:马哥Linux运维】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    使用nginx实现tomcat负载均衡

    Nginx+tomcat+memcached实现负载均衡及session(交叉存储)
    发表于 08-28 08:52

    采用Nginx反向代理解决跨域

    40Nginx反向代理功能解决跨域问题
    发表于 10-10 10:58

    nginx实现的负载均衡

    nginx实现负载均衡
    发表于 05-04 13:42

    16nginx+keepalived +zuul如何实现高可用及负载均衡

    学习笔记微服务-16 nginx+keepalived +zuul 实现高可用及负载均衡
    发表于 05-22 10:16

    Nginx和Tomcat负载均衡实现session共享

    Nginx和Tomcat负载均衡实现session共享
    发表于 09-05 10:40 9次下载
    <b class='flag-5'>Nginx</b>和Tomcat<b class='flag-5'>负载</b><b class='flag-5'>均衡</b>实现session共享

    构建实战Nginx+IIS构筑Web服务器集群负载均衡

    构建实战Nginx+IIS构筑Web服务器集群负载均衡
    发表于 09-05 10:56 4次下载
    构建<b class='flag-5'>实战</b>:<b class='flag-5'>Nginx</b>+IIS构筑Web服务器集群<b class='flag-5'>负载</b><b class='flag-5'>均衡</b>

    apache反向代理负载均衡总结

    apache反向代理负载均衡总结(5g电源技术要求)-apache反向代理
    发表于 08-31 12:27 1次下载
    apache<b class='flag-5'>反向</b><b class='flag-5'>代理</b>和<b class='flag-5'>负载</b><b class='flag-5'>均衡</b>总结

    聊聊Nginx作为负载均衡器它支持的算法都有哪些?

    Nginx作为一款最流行WEB服务器软件,同时也是一款反向代理负载均衡软件。毫不夸张地说,Nginx
    的头像 发表于 02-14 17:50 1543次阅读

    如何使用Nginx作为应用程序的负载均衡器?

    Nginx因其高性能和可扩展性而广受欢迎。它是排名第一的开源Web 服务器。在本教程中,我们将学习如何使用Nginx作为应用程序的负载均衡器? 要将
    的头像 发表于 03-23 14:52 2127次阅读

    搭建Keepalived+Lvs+Nginx高可用集群负载均衡

      一、Nginx安装 二、配置反向代理 三、配置负载均衡
    的头像 发表于 06-25 15:39 4491次阅读
    搭建Keepalived+Lvs+<b class='flag-5'>Nginx</b>高可用集群<b class='flag-5'>负载</b><b class='flag-5'>均衡</b>

    nginx使用学习之正、反向代理

    Nginx 不仅可以做反向代理,实现负载均衡。还能用作正向代理来进行上网等功能。正向
    的头像 发表于 11-13 10:54 2177次阅读
    <b class='flag-5'>nginx</b>使用学习之正、<b class='flag-5'>反向</b><b class='flag-5'>代理</b>

    如何使用nginx反向代理功能?保姆级教程!

    一关于nginxnginx是一款高性能的开源Web服务器软件,也可以用于反向代理负载均衡等,并且具有高性能、低内存消耗等优点。本文我们主要讲解关于
    的头像 发表于 06-21 08:21 2013次阅读
    如何使用<b class='flag-5'>nginx</b><b class='flag-5'>反向</b><b class='flag-5'>代理</b>功能?保姆级教程!

    nginx负载均衡配置介绍

    目录 nginx负载均衡 nginx负载均衡介绍 反向
    的头像 发表于 11-10 13:39 1794次阅读
    <b class='flag-5'>nginx</b><b class='flag-5'>负载</b><b class='flag-5'>均衡</b><b class='flag-5'>配置</b>介绍

    Nginx代理转发实战:零基础掌握服务器流量分发技巧

    Nginx 是最常用的反向代理工具之一,一个指令 proxy_pass搞定反向代理,对于接口代理
    的头像 发表于 12-09 12:28 3231次阅读

    Nginx典型配置错误复盘与优化

    Nginx 是互联网生产环境中使用最广泛的反向代理和 Web 服务器之一。不管是做静态资源服务、API 网关,还是负载均衡器,
    的头像 发表于 05-12 09:40 378次阅读