🎯 核心问题

在高并发的互联网架构中,如何把流量安全、高效地送到正确的服务? 反向代理解决"流量怎么分发",API网关解决"请求怎么处理"。本文通过真实案例(前台接待、保安系统、智能路由)深入理解网关的设计哲学和工程实践。


1. 为什么要"网关"?

1.1 从一个真实案例说起:某电商的架构演进

某电商平台在业务快速增长时遇到了严重的架构问题:

场景还原:

  阶段一:直接暴露服务
客户端 → 直接调用用户服务、订单服务、支付服务...
         ↓
问题1:服务IP暴露,存在安全隐患
问题2:无法统一做认证、限流
问题3:新增服务需要修改客户端配置
  
⚠️ 直接暴露的致命问题
  • 安全隐患: 所有服务IP暴露,容易被攻击
  • 功能重复: 每个服务都要做认证、限流、日志
  • 扩展困难: 新增服务要修改所有客户端
  • 协议混乱: 有的用HTTP,有的用gRPC,客户端要适配 :::

改进后的架构(引入网关):

  客户端 → API网关(Nginx/Kong) → 内部服务
         ↓
      统一认证、限流、路由
         ↓
      客户端只知道网关地址
  
✨ 改进后的效果
  • 安全: 真实服务IP隐藏,只有网关对外
  • 功能收敛: 认证、限流、日志在网关统一处理
  • 扩展容易: 新增服务只需网关配置路由
  • 协议统一: 对外HTTP,内部可用gRPC :::

1.2 网关的生活化比喻

前台接待

想象你去一家大公司:

  • 没有前台: 访客直接找各部门,不知道在哪,公司乱成一团
  • 有前台: 访客先到前台,前台问清楚来意,再引导到对应部门

API网关就是系统的"前台":

  • 反向代理: 前台,引导访客到正确的部门
  • API网关: 智能前台,还能检查访客身份(认证)、限制访问人数(限流)

2. 什么是反向代理?

2.1 正向代理 vs 反向代理

🤔 术语解释

正向代理(Forward Proxy):

  • 部署在客户端侧
  • 代替客户端访问外部资源
  • 典型应用:VPN、翻墙工具
  • 例子:公司网络,你通过代理访问外网

反向代理(Reverse Proxy):

  • 部署在服务器端
  • 接收客户端请求并转发给内部服务
  • 客户端只知道代理存在,不知道真实服务器
  • 例子:Nginx、HAProxy :::

对比表:

维度 正向代理 反向代理
部署位置 客户端侧 服务器端
服务对象 客户端 服务器
典型应用 VPN、翻墙 负载均衡、网关
透明性 服务器看到代理IP 客户端看到代理IP
目的 隐藏真实客户端、加速访问 隐藏真实服务器、负载均衡

2.2 反向代理的核心价值

价值一:负载均衡 将流量分发到多个后端服务器,避免单点过载。
  客户端
  ↓
Nginx(反向代理)
  ↓
┌─────────┬─────────┬─────────┐
│ 服务器1 │ 服务器2 │ 服务器3 │
└─────────┴─────────┴─────────┘
  
价值二:安全防护 隐藏真实服务器IP,防止直接攻击。统一在代理层做安全防护。
  客户端 → 只能看到Nginx的IP
真实服务器 → 只在内网,外部无法直接访问
  
价值三:SSL终结 在代理层处理HTTPS加密解密,后端服务用HTTP,降低后端计算开销。
  HTTPS客户端 → Nginx(加密/解密) → HTTP后端服务
                   ↑
              SSL终结点
  

3. Nginx:为什么能扛起百万并发?

3.1 Master-Worker进程模型

Nginx采用多进程架构,而不是多线程:

Master进程(管理者):

  • 负责读取和验证配置文件
  • 管理Worker进程(启动、停止、重新加载)
  • 不处理具体请求

Worker进程(工作者):

  • 实际处理HTTP请求
  • 每个Worker是独立的进程,相互隔离
  • 数量通常设置为CPU核心数,避免上下文切换开销
💡 优势
  • 隔离性好: 一个Worker崩溃,不影响其他Worker
  • 充分利用多核: 每个Worker独立运行
  • 避免多线程复杂性: 无需处理锁、竞争等问题 :::

3.2 事件驱动 + 异步非阻塞

这是Nginx高性能的核心秘密:

传统Apache(多进程/线程模型):

  • 一个连接 = 一个进程/线程
  • 并发数受限于系统进程/线程数
  • 大量连接时,进程切换开销巨大

Nginx(事件驱动模型):

  • 使用epoll(Linux)/kqueue(macOS)等高效I/O多路复用机制
  • 一个Worker进程可以同时处理数万个连接
  • 连接没有数据时,不会占用CPU,有新数据时通过事件通知唤醒
生活化比喻
  • Apache: 餐厅里每个顾客配一个服务员(进程),顾客多需要大量服务员
  • Nginx: 一个超级服务员,同时服务所有顾客,谁需要服务就去谁那里,而不是一直站在某个顾客旁边 :::

4. 什么是API网关?

4.1 为什么需要API网关?

想象一个没有网关的系统:

  • 客户端需要知道多个服务的地址(用户服务、订单服务、支付服务…)
  • 每个服务都要自己做认证、限流、日志
  • 协议不统一,有的用HTTP,有的用gRPC
  • 服务升级时,客户端也需要跟着改
⚠️ 没有网关的问题
  • 客户端复杂: 需要配置多个服务地址
  • 功能重复: 每个服务都要实现认证、限流
  • 协议混乱: 客户端要适配多种协议
  • 升级困难: 服务升级,客户端也要改 :::

有了API网关之后:

  • 客户端只需要知道网关地址,网关负责路由到正确服务
  • 认证、限流、日志等横切逻辑统一在网关处理
  • 网关可以做协议转换,对外统一暴露HTTP
  • 后端服务升级,只需要改网关配置,客户端无感知

4.2 API网关的核心功能

功能 说明 典型场景
路由转发 根据URL、Header等规则,将请求转发到不同服务 /api/users → 用户服务,/api/orders → 订单服务
负载均衡 同一个服务有多实例时,分摊流量 用户服务有3台实例,轮询分发请求
认证鉴权 统一校验JWT、OAuth Token 未登录用户无法访问/api/admin
限流熔断 控制流量上限,防止服务被压垮 每秒最多1000请求,超过返回429
协议转换 对外HTTP,内部可转gRPC 客户端用HTTP,网关转gRPC调用内部服务
灰度发布 按Header或比例,将部分流量导到新版本 5%用户体验新版本,95%用旧版本
日志监控 统一记录请求日志,便于分析和排障 记录每次请求的耗时、状态码、返回大小

5. 网关实战:如何构建完整的网关架构?

5.1 完整架构图

  ┌───────────────────────────────────────────────────────────────────────┐
│                           客户端(浏览器/APP)                               │
└───────────────────────────┬─────────────────────────────────────────┘
                                │ HTTPS
                                ▼
┌───────────────────────────────────────────────────────────────────────┐
│                        外层:CDN + WAF                                  │
│  ┌─────────────────────────────────────────────────────────────┐  │
│  │  CDN(内容分发网络)                                        │  │
│  │  - 静态资源缓存(图片、CSS、JS)                           │  │
│  │  - 就近访问,降低延迟                                   │  │
│  └───────────────────────────────────────────────────────────────┘  │
│  ┌───────────────────────────────────────────────────────────────┐  │
│  │  WAF(Web应用防火墙)                                     │  │
│  │  - 防护SQL注入、XSS攻击                                │  │
│  │  - 拦截恶意Bot、爬虫                                  │  │
│  │  - CC攻击防护                              │  │
│  └───────────────────────────────────────────────────────────────┘  │
└───────────────────────────────────────────────────────────────────────┘
                                │
                                ▼
┌───────────────────────────────────────────────────────────────────────┐
│                     中层:API网关(Nginx/Kong)                      │
│  ┌───────────────────────────────────────────────────────────────┐  │
│  │  第一层:SSL终结 + 安全防护                              │  │
│  │  - HTTPS / TLS 1.3                                        │  │
│  │  - HSTS、安全响应头                                        │  │
│  └───────────────────────────────────────────────────────────────┘  │
│  ┌───────────────────────────────────────────────────────────────┐  │
│  │  第二层:认证与鉴权                                      │  │
│  │  - JWT Token校验                                         │  │
│  │  - OAuth 2.0 / SSO集成                                     │  │
│  │  - API Key管理                                         │  │
│  │  - 权限校验(RBAC)                                        │  │
│  └───────────────────────────────────────────────────────────────┘  │
│  ┌───────────────────────────────────────────────────────────────┐  │
│  │  第三层:流量控制                                        │  │
│  │  - 限流- 令牌桶/漏桶算法                             │  │
│  │  - 熔断- 防止故障扩散                                 │  │
│  │  - 降级- 服务不可用时的备用方案                         │  │
│  │  - 灰度发布- 按比例分配流量                          │  │
│  └───────────────────────────────────────────────────────────────┘  │
│  ┌───────────────────────────────────────────────────────────────┐  │
│  │  第四层:路由与负载均衡                                    │  │
│  │  - 路径路由- Path-based Routing)                          │  │
│  │  - 域名路由- Host-based Routing)                           │  │
│  │  - Header路由- Header-based Routing)                             │  │
│  │  - 负载均衡算法- 轮询/加权/最少连接/IP哈希)             │  │
│  │  - 服务发现- Service Discovery)集成                        │  │
│  └───────────────────────────────────────────────────────────────┘  │
│  ┌───────────────────────────────────────────────────────────────┐  │
│  │  第五层:协议转换与数据处理                                 │  │
│  │  - SSL终结- HTTPS ↔ HTTP)                                   │  │
│  │  - 协议转换- HTTP ↔ gRPC / WebSocket)                         │  │
│  │  - 请求/响应转换- JSON ↔ XML)                               │  │
│  │  - 数据压缩- Gzip / Brotli)                                   │  │
│  │  - 缓存- Cache)- 静态资源和API响应                          │  │
│  └───────────────────────────────────────────────────────────────┘  │
└───────────────────────────────────────────────────────────────────────┘
                                │
                                ▼
┌───────────────────────────────────────────────────────────────────────┐
│                        内层:微服务集群                             │
│  ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐      │
│  │  用户服务    │ │  订单服务    │ │  商品服务    │ │  支付服务    │      │
│  │  User Svc   │ │  Order Svc  │ │ Product Svc │ │ Payment Svc │      │
│  │             │ │             │ │             │ │             │      │
│  └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘      │
│         │                │                │                │               │
│         └────────────────┴────────────────┴────────────────┘               │
│                                       │                              │
│                    服务发现与配置中心/ etcd)                          │
│                    - 服务注册与发现                                      │
│                    - 健康检查                                              │
│                    - KV配置存储                                              │
└───────────────────────────────────────────────────────────────────────┘
  

5.2 路由与负载均衡

网关的核心职责之一,就是把请求送到正确的地方。这涉及两个关键能力:路由(去哪台服务器)和负载均衡(怎么分配流量)。

路由规则:从URL到服务 想象一个电商系统,不同的URL对应不同的服务:
  • /api/users/* → 用户服务
  • /api/orders/* → 订单服务
  • /api/products/* → 商品服务
  • /api/pay/* → 支付服务

Nginx配置示例:

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

    # 用户服务
    location /api/users/ {
        proxy_pass http://user-service;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # 订单服务
    location /api/orders/ {
        proxy_pass http://order-service;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # 商品服务
    location /api/products/ {
        proxy_pass http://product-service;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # 支付服务(需要更高安全级别)
    location /api/pay/ {
        # 限制IP访问
        allow 10.0.0.0/8;
        deny all;

        proxy_pass http://payment-service;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}
  
负载均衡:四种策略对比 当同一个服务有多个实例时,如何选择?
策略 原理 适用场景 优点 缺点
轮询 按顺序依次分配给每台服务器 服务器性能相近 简单公平 不考虑服务器当前负载
加权轮询 按权重比例分配,权重高的分配更多 服务器性能不均 充分利用高性能服务器 需要合理设置权重
最少连接 分配给当前连接数最少的服务器 长连接场景、视频流 动态适应负载变化 需要实时统计连接数
IP哈希 根据客户端IP计算哈希,同一IP永远分配到同一台服务器 需要会话保持 保证会话一致性 某个IP流量大时会造成单点压力

Nginx配置示例:

  # 加权轮询
upstream backend_weighted {
    server 10.0.1.10:8080 weight=3;  # 性能好,承担更多流量
    server 10.0.1.11:8080 weight=2;
    server 10.0.1.12:8080 weight=1;  # 性能差,承担较少流量
}

# 最少连接
upstream backend_least_conn {
    least_conn;
    server 10.0.1.10:8080;
    server 10.0.1.11:8080;
    server 10.0.1.12:8080;
}

# IP哈希(会话保持)
upstream backend_ip_hash {
    ip_hash;
    server 10.0.1.10:8080;
    server 10.0.1.11:8080;
    server 10.0.1.12:8080;
}
  

6. 网关安全:如何守护系统大门?

6.1 认证与鉴权

传统方式(每个服务各自认证):

  • 用户服务、订单服务、支付服务…每个都要校验JWT
  • 代码重复,维护困难
  • secret分散在各个服务,泄露风险高

网关统一认证:

  • 客户端携带Token访问网关
  • 网关校验Token合法性(签名、过期时间)
  • 校验通过后,将用户信息(如user_id)添加到请求头,转发给后端服务
  • 后端服务无需校验,直接从Header获取用户信息
💡 核心思想

认证在网关,鉴权在服务:

  • 认证: 你是谁?(校验Token,获取用户身份)
  • 鉴权: 你能做什么?(根据用户角色判断权限)

就像公司前台:前台认证你的身份(身份证),但具体权限由各部门判断。

6.2 HTTPS与SSL终结

为什么需要HTTPS?

  1. 安全: 防止数据在传输过程中被窃取
  2. 合规: 现代浏览器对HTTP网站显示"不安全"警告
  3. SEO: 搜索引擎优先收录HTTPS网站

SSL终结方案:

  • 只在网关层配置HTTPS和证书
  • 网关负责TLS握手和加解密
  • 网关和后端服务之间使用HTTP明文传输(内部网络可信)
  • 后端服务专注于业务逻辑,无需处理TLS
💡 SSL终结的优势
  • 简化管理: 证书只在网关配置,后端无需配置
  • 降低开销: 后端服务不需要处理TLS握手
  • 统一更新: 证书更新只需在网关操作 :::

7. 限流与熔断:如何防止系统被"流量洪水"冲垮?

7.1 限流算法对比

算法 核心思想 突发流量 适用场景 实现复杂度
令牌桶 桶里装令牌,有令牌才能通过 允许一定程度的突发 API限流、带宽控制 中等
漏桶 请求进桶,匀速流出处理 强制平滑,突发会被缓存或拒绝 需要严格匀速处理的场景 中等
滑动窗口 统计时间窗口内的请求数 严格按窗口计数,超出一律拒绝 精确统计(如"1分钟内最多100次") 较高

7.2 Nginx限流配置实战

  # 定义限流区域(放在http块中)

# 1. 基于IP的限流(漏桶算法)
# zone=mylimit:10m - 区域名称和内存大小(10MB约可存储16万IP)
# rate=10r/s - 每秒允许10个请求
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;

# 2. 基于IP的连接数限制(防止单个IP建立过多连接)
limit_conn_zone $binary_remote_addr zone=addr:10m;

# 3. 基于服务端点的限流(不区分IP,保护后端整体)
limit_req_zone $server_name zone=server_limit:10m rate=100r/s;

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

    # 用户服务 - 普通限流
    location /api/users/ {
        # 应用限流
        # burst=20 - 桶容量,允许突发20个请求
        # nodelay - 不延迟处理突发请求(立即处理或拒绝)
        limit_req zone=mylimit burst=20 nodelay;

        # 限制单个IP的连接数
        limit_conn addr 10;

        proxy_pass http://user-service;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # 订单服务 - 更严格的限流
    location /api/orders/ {
        # 更严格的限流:每秒5个请求
        limit_req_zone $binary_remote_addr zone=order_limit:10m rate=5r/s;
        limit_req zone=order_limit burst=10 nodelay;

        proxy_pass http://order-service;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # 限流后的处理
    # 当请求被限流时,返回429 Too Many Requests
    error_page 429 /429.html;
    location = /429.html {
        internal;
        return 429 '{"error": "Too Many Requests", "message": "Rate limit exceeded. Please try again later."}';
        add_header Content-Type application/json;
    }
}
  
💡 限流策略建议
  • 普通接口: 每秒10个请求,允许突发20个
  • 重要接口(支付、订单): 每秒5个请求,允许突发10个
  • 全局保护: 所有请求总和不超过每秒100个 :::

7.3 熔断:防止故障扩散

熔断器的工作原理:

  1. 关闭状态: 正常转发请求,同时统计错误率
  2. 开启状态: 当错误率超过阈值,熔断器开启,直接返回错误,不再转发请求
  3. 半开状态: 经过一段时间后,允许少量请求通过试探,如果成功则关闭熔断器
💡 核心思想

熔断就像电路保险丝: 电流过大时,保险丝自动熔断,保护整个电路不被烧毁。

类似地,当后端服务出现大量错误时,熔断器"跳闸",快速失败,防止故障扩散到整个系统。


8. 总结:网关设计的核心思维

8.1 核心原则回顾

原则 含义 实践要点
路由 把请求送到正确的地方 路径路由、域名路由、Header路由
负载均衡 分摊流量到多台服务器 轮询、加权、最少连接、IP哈希
安全 守护系统大门 认证鉴权、HTTPS、WAF
限流 防止被流量冲垮 令牌桶、漏桶、滑动窗口
熔断 防止故障扩散 快速失败、降级方案
可观测 监控和排障 日志、指标、链路追踪

8.2 技术选型建议

💡 选型决策树
  选择网关:
│
├─ 只需要反向代理、负载均衡?
│  ├─ 是 → Nginx(首选)
│  └─ 否 → 继续
│
├─ 需要丰富的插件生态?
│  ├─ 是 → Kong(基于Nginx)
│  └─ 否 → 继续
│
├─ Spring Cloud 全家桶?
│  ├─ 是 → Spring Cloud Gateway
│  └─ 否 → Nginx
  

9. 名词速查表

名词 英文 解释
反向代理 Reverse Proxy 部署在服务器端,接收客户端请求并转发给内部服务的代理服务。客户端只知道反向代理的存在,不知道真实服务器地址。
正向代理 Forward Proxy 部署在客户端侧,代替客户端访问外部资源的代理服务。服务端看到的是代理的IP,不知道真实客户端。典型应用:VPN、翻墙工具。
API网关 API Gateway 位于客户端和后端服务之间的中间层,提供路由、认证、限流、日志等功能,是微服务架构的"统一大门"。
负载均衡 Load Balancing 将请求流量分配到多台服务器,避免单台服务器过载,提高系统可用性和性能。
SSL终结 SSL Termination 在网关层处理HTTPS加密解密,后端服务使用HTTP,降低后端计算开销,简化证书管理。
限流 Rate Limiting 限制单位时间内的请求数量,防止系统被突发流量压垮。常用算法:令牌桶、漏桶、滑动窗口。
熔断 Circuit Breaking 当依赖服务出现故障时,自动切断调用,防止故障扩散,并提供降级方案。
会话保持 Session Persistence 确保同一客户端的请求始终路由到同一台后端服务器,用于需要保持会话状态的场景。
健康检查 Health Check 定期检查后端服务的健康状态,自动剔除故障节点,保证流量只发送到健康的服务实例。
灰度发布 Canary Release 将少量流量导到新版本,验证稳定性后逐步扩大比例,降低发布风险。
WAF Web Application Firewall Web应用防火墙,防护SQL注入、XSS、CC攻击等Web安全威胁。
CDN Content Delivery Network 内容分发网络,在全球部署边缘节点,加速静态资源访问。

Last updated 26 Apr 2026, 03:21 +0800 . history