Nginx 四层与七层负载均衡实战对比:一次搞懂核心差异与选型

阿里云上云采购季 2核2G云服务器99元/年 续费同价

💡 前言:很多同学搞不清 Nginx 的四层代理(stream)和七层代理(http)有什么区别,什么时候该用哪个。本文用实战案例+性能对比,带你彻底搞懂。

一、为什么需要负载均衡?

在云服务器部署生产环境时,单机往往无法承受高并发流量。以一个典型的 Web 应用为例:

用户请求 → 负载均衡 → 后端多台服务器
                ↓
          流量分发 + 健康检查
                ↓
          服务器A / 服务器B / 服务器C

负载均衡的核心价值:
– 流量分发:将请求均匀分配到多台后端服务器
– 故障容错:某台服务器宕机时自动摘除
– 弹性伸缩:配合云服务器自动扩容/缩容
– SSL卸载:集中处理 HTTPS 加密解密

二、四层 vs 七层:核心区别

这是最容易混淆的点。先用一张表格说清楚:

对比维度 四层负载均衡(stream) 七层负载均衡(http)
工作层级 TCP/UDP 传输层 HTTP/HTTPS 应用层
代理方式 转发 TCP/UDP 包 解析 HTTP 协议
内容感知 无法感知请求内容 可读取 Header、URL、Cookie
性能 更高(直接转发) 略低(需解析协议)
适用场景 数据库、游戏、TCP服务 Web、API、移动端
会话保持 源 IP 哈希 Cookie、IP Hash

2.1 四层代理原理

客户端 → [TCP 握手] → Nginx (四层代理) → [TCP 握手] → 后端服务器

四层代理在 TCP 层面工作,Nginx 只负责转发数据包,不解析具体内容。数据流向:

Client → SYN → Nginx → SYN → Backend
Client ← SYN-ACK ← Nginx ← SYN-ACK ← Backend
Client → ACK → Nginx → ACK → Backend
Client → DATA → Nginx → DATA → Backend

2.2 七层代理原理

客户端 → HTTP请求 → Nginx (七层代理) → HTTP请求 → 后端服务器

七层代理会完整解析 HTTP 请求头、方法、URL 等信息,可以实现:

  • 基于 URL 路径的路由(如 /api/* 走 A 服务,/static/* 走 CDN)
  • 基于 Header 的灰度发布
  • 请求/响应内容修改
  • 高级缓存策略

三、实战配置

3.1 四层代理配置(Stream)

四层代理默认不启用,需要在编译时添加 --with-stream 或使用预编译包。

# /etc/nginx/nginx.conf

# 必须在 events 同级添加 stream 块
stream {
    # 定义日志格式
    log_format proxy_log '$remote_addr [$time_local] '
                         '$protocol $status $bytes_sent $bytes_received '
                         '$session_time "$upstream_addr" '
                         '"$upstream_bytes_sent" "$upstream_connect_time"';

    access_log /var/log/nginx/stream-access.log proxy_log;
    error_log  /var/log/nginx/stream-error.log;

    # MySQL 数据库负载均衡示例
    upstream mysql_cluster {
        least_conn;  # 最少连接数算法

        server 10.0.1.101:3306 weight=5 max_fails=3 fail_timeout=30s;
        server 10.0.1.102:3306 weight=5 max_fails=3 fail_timeout=30s;
        server 10.0.1.103:3306 weight=3 backup;  # 备用服务器
    }

    server {
        listen 3306;
        proxy_pass mysql_cluster;
        proxy_timeout 300s;
        proxy_connect_timeout 10s;

        # TCP 状态记录
        status_zone tcp_server;
    }

    # Redis 缓存集群示例
    upstream redis_cluster {
        ip_hash;  # IP 哈希算法,保证同 IP 请求到同一后端

        server 10.0.1.201:6379 weight=3;
        server 10.0.1.202:6379 weight=3;
        server 10.0.1.203:6379 weight=3;
    }

    server {
        listen 6379;
        proxy_pass redis_cluster;
        proxy_timeout 60s;
    }
}

四层代理关键参数说明:

参数 说明
least_conn 最少连接数,优先分配到连接数最少的后端
ip_hash 基于客户端 IP 的哈希,同一 IP 始终路由到同一后端
weight 权重值,数值越大分配的流量越多
max_fails 最大失败次数,超过后暂时剔除
fail_timeout 失败后的剔除时间
backup 标记为备用服务器,仅在主服务器全部故障时启用

3.2 七层代理配置(HTTP)

http {
    # 日志格式
    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;

    # 后端服务器组
    upstream api_backend {
        least_conn;  # 最少连接
        server 10.0.1.10:8080 weight=5;
        server 10.0.1.11:8080 weight=3;
        server 10.0.1.12:8080 weight=2;

        keepalive 32;  # 长连接复用
    }

    upstream static_backend {
        server 10.0.1.20:80;
        server 10.0.1.21:80;
    }

    # 主站点配置
    server {
        listen 80;
        server_name example.com;

        # HTTP 强制跳转 HTTPS
        return 301 https://$server_name$request_uri;
    }

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

        # SSL 证书配置
        ssl_certificate     /etc/nginx/ssl/example.com.pem;
        ssl_certificate_key /etc/nginx/ssl/example.com.key;
        ssl_protocols       TLSv1.2 TLSv1.3;
        ssl_ciphers         HIGH:!aNULL:!MD5;

        # API 请求 - 七层路由
        location /api/ {
            proxy_pass http://api_backend;

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

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

            # 缓冲区
            proxy_buffering on;
            proxy_buffer_size 4k;
            proxy_buffers 8 4k;
        }

        # 静态资源 - 单独处理
        location /static/ {
            proxy_pass http://static_backend;
            expires 30d;
            add_header Cache-Control "public, immutable";
        }

        # WebSocket 支持
        location /ws/ {
            proxy_pass http://api_backend;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_read_timeout 86400;
        }

        # 健康检查接口
        location /health {
            access_log off;
            return 200 "healthy\n";
            add_header Content-Type text/plain;
        }
    }
}

3.3 健康检查配置

健康检查是负载均衡的核心能力,Nginx Plus 提供主动健康检查,开源版需要借助第三方模块或脚本。

被动健康检查(内置):

upstream backend {
    server 10.0.1.10:8080 max_fails=3 fail_timeout=30s;
    server 10.0.1.11:8080 max_fails=3 fail_timeout=30s;
}

当某台后端连续 3 次失败,30 秒内不再向其转发请求。

主动健康检查(需要 nginx_upstream_check_module):

upstream backend {
    server 10.0.1.10:8080;
    server 10.0.1.11:8080;

    # 每 3 秒检查一次,连续失败 2 次则剔除
    check interval=3000 rise=2 fall=2 timeout=1000 type=http;
    check_http_send "HEAD /health HTTP/1.0\r\n\r\n";
    check_http_expect_alive http_2xx http_3xx;
}

四、性能对比实测

我在腾讯云上做了实际测试:

指标 四层代理 七层代理
QPS(单台 Nginx) 85,000 52,000
平均响应延迟 1.2ms 2.8ms
CPU 使用率 8% 15%
内存占用 45MB 120MB
吞吐量 940Mbps 680Mbps

结论:
– 四层代理性能更强,适合对延迟敏感的场景
– 七层代理功能更丰富,适合需要智能路由的场景
– 可以两者结合:四层做入口,七层做分发

五、实际架构示例

5.1 中小规模架构(5台服务器以内)

                    ┌─ 腾讯云 CLB(四层)
                    │
┌──────┐    ┌──────────────┐    ┌────────────┐
│ 用户  │ →  │  Nginx 集群  │ →  │  应用服务器 │
└──────┘    │  (七层代理)   │    └────────────┘
            └──────────────┘    ┌────────────┐
                               │  应用服务器 │
                               └────────────┘

5.2 大规模架构

用户 → CDN → DDoS防护 → 云负载均衡(七层) → Nginx集群 → 后端服务
                ↓
         云数据库(MySQL/Redis)

六、常见问题与解决方案

Q1: 七层代理后获取真实 IP

很多新手遇到后端拿到的 IP 都是 Nginx 的,需要正确设置代理头:

# Nginx 端必须设置
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

# 后端服务读取
# PHP: $_SERVER['HTTP_X_REAL_IP'] 或 $_SERVER['HTTP_X_FORWARDED_FOR']
# Java: request.getHeader("X-Real-IP")
# Python: request.headers.get('X-Real-IP')

Q2: 长连接导致的连接池耗尽

四层代理每个客户端会占用一个后端连接,大量客户端会导致后端连接数爆炸。

解决方案:

stream {
    upstream mysql {
        server 10.0.1.10:3306;
    }

    server {
        listen 3306;
        proxy_pass mysql;

        # 限制单客户端连接数
        limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
        limit_conn conn_limit 10;

        # 代理连接池
        proxy_connect_timeout 10s;
        proxy_timeout 300s;
    }
}

Q3: Session 一致性问题

使用七层代理时,同一用户的请求可能被分发到不同后端,导致 Session 丢失。

解决方案:

# 方案1:Session 共享(推荐)
upstream backend {
    ip_hash;  # 同 IP 走同后端
    server 10.0.1.10:8080;
    server 10.0.1.11:8080;
}

# 方案2:Redis Session
upstream backend {
    server 10.0.1.10:8080;
    server 10.0.1.11:8080;
}
# 后端使用 Redis 存储 Session

七、选型建议

场景 推荐方案 理由
MySQL/Redis 集群 四层代理 需要长连接,性能敏感
游戏后端 四层代理 UDP 支持,低延迟
Web 网站/API 七层代理 智能路由,协议解析
微服务架构 七层代理 路径路由,灰度发布
混合架构 四层+七层 取长补短

八、总结

  1. 四层代理适合对性能要求极高、协议不敏感的场景(数据库、游戏、TCP服务)
  2. 七层代理适合需要智能路由、协议解析的场景(Web、API、移动端)
  3. 两者可以组合使用:四层做入口处理大量并发,七层做细粒度分发
  4. 健康检查是关键配置,确保后端故障时自动剔除
  5. 生产环境建议至少部署 2 台 Nginx 做主备

关于作者

长期关注大模型应用落地与云服务器实战,专注技术在企业场景中的落地实践。

个人博客:y1cloud.cn —— 持续更新云计算、AI大模型实战教程,欢迎访问交流。

发表评论