一、为什么需要API网关

在微服务架构中,客户端直接调用后端服务会带来诸多问题:

  • 客户端复杂度高:需要知道所有服务地址,调用逻辑复杂
  • 横切关注点重复:每个服务都要实现认证、限流、日志
  • 安全风险:后端服务直接暴露,存在安全漏洞
  • 难以统一治理:无法统一监控、限流、降级

API网关作为统一入口:

  • 路由转发:请求路由到后端服务
  • 负载均衡:多实例负载
  • 认证授权:统一身份认证
  • 限流熔断:流量控制
  • 日志监控:请求链路追踪

二、Kong网关实战

1. 安装部署

Docker方式:

# 创建网络
docker network create kong-net

# 启动PostgreSQL(Kong的数据库)
docker run -d \
    --name kong-database \
    --network=kong-net \
    -p 5432:5432 \
    -e "POSTGRES_USER=kong" \
    -e "POSTGRES_DB=kong" \
    -e "POSTGRES_PASSWORD=kong" \
    postgres:13

# 初始化Kong数据库
docker run --rm \
    --network=kong-net \
    -e "KONG_DATABASE=postgres" \
    -e "KONG_PG_HOST=kong-database" \
    -e "KONG_PG_PASSWORD=kong" \
    -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \
    -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \
    kong:latest kong migrations bootstrap

# 启动Kong
docker run -d \
    --name kong \
    --network=kong-net \
    -e "KONG_DATABASE=postgres" \
    -e "KONG_PG_HOST=kong-database" \
    -e "KONG_PG_PASSWORD=kong" \
    -e "KONG_PROXY_LISTEN=0.0.0.0:8000" \
    -e "KONG_ADMIN_LISTEN=0.0.0.0:8001" \
    -p 8000:8000 \
    -p 8443:8443 \
    -p 8001:8001 \
    -p 8444:8444 \
    kong:latest

DB-less模式(无数据库):

# docker-compose.yml
version: '3'
services:
  kong:
    image: kong:latest
    environment:
      KONG_DATABASE: off
      KONG_DECLARATIVE_CONFIG: /usr/local/kong/kong.yml
    volumes:
      - ./kong.yml:/usr/local/kong/kong.yml
    ports:
      - "8000:8000"
      - "8443:8443"

2. 添加服务

方式一:Admin API

# 添加服务
curl -X POST http://localhost:8001/services/ \
  --data "name=order-service" \
  --data "url=http://order-service:8080" \
  --data "protocol=http"

# 添加路由
curl -X POST http://localhost:8001/services/order-service/routes/ \
  --data "name=order-route" \
  --data "paths[]=/order" \
  --data "methods[]=GET" \
  --data "methods[]=POST"

# 验证
curl -i http://localhost:8000/order/list

方式二:Declarative配置

# kong.yml
_format_version: "3.0"
services:
  - name: order-service
    url: http://order-service:8080
    routes:
      - name: order-route
        paths:
          - /order
        methods:
          - GET
          - POST
    plugins:
      - name: rate-limiting
        config:
          second: 100
          policy: local

  - name: user-service
    url: http://user-service:8080
    routes:
      - name: user-route
        paths:
          - /user
    plugins:
      - name: jwt

3. 插件配置

限流插件:

# 本地限流(每分钟100次)
curl -X POST http://localhost:8001/services/order-service/plugins/ \
  --data "name=rate-limiting" \
  --data "config.second=100" \
  --data "config.minute=1000" \
  --data "config.policy=local"

# Redis限流(分布式限流)
curl -X POST http://localhost:8001/services/order-service/plugins/ \
  --data "name=rate-limiting" \
  --data "config.second=100" \
  --data "config.policy=redis" \
  --data "config.redis_host=redis-server" \
  --data "config.redis_port=6379"

JWT认证插件:

curl -X POST http://localhost:8001/services/user-service/plugins/ \
  --data "name=jwt" \
  --data "config.uri_param_names=jwt" \
  --data "config.cookie_names=token"

CORS跨域插件:

curl -X POST http://localhost:8001/services/order-service/plugins/ \
  --data "name=cors" \
  --data "config.origins=*" \
  --data "config.methods=GET,POST,PUT,DELETE" \
  --data "config.headers=Content-Type,Authorization" \
  --data "config.exposed_headers=X-Total-Count" \
  --data "config.credentials=true" \
  --data "config.max_age=3600"

请求转换插件:

curl -X POST http://localhost:8001/services/order-service/plugins/ \
  --data "name=request-transformer" \
  --data "config.add.headers=X-Kong-Request-ID:$(uuidgen)" \
  --data "config.remove.headers=User-Agent"

三、APISIX网关实战

1. 安装部署

Docker Compose方式:

# docker-compose.yml
version: '3'
services:
  apisix:
    image: apache/apisix:latest
    environment:
      APISIX_DEFAULTS: |
        nginx_config:
          worker_rlimit_nofile: 65536
    volumes:
      - ./apisix/config.yaml:/usr/local/apisix/conf/config.yaml
      - ./apisix/routes.yaml:/usr/local/apisix/conf/routes.yaml
    ports:
      - "9080:9080"
      - "9443:9443"
    depends_on:
      - etcd
  
  etcd:
    image: bitnami/etcd:latest
    environment:
      - ALLOW_NONE_AUTHENTICATION=yes
      - ETCD_ADVERTISE_CLIENT_URLS=http://etcd:2379
    volumes:
      - etcd_data:/bitnami/etcd

volumes:
  etcd_data:

2. 配置示例

静态路由配置:

# routes.yaml
routes:
  # 订单服务路由
  - id: order-service
    uri: /order/*
    upstream:
      type: roundrobin
      nodes:
        "order-service-1:8080": 1
        "order-service-2:8080": 1
    plugins:
      # 限流
      limit-req:
        rate: 100
        burst: 200
        rejected_code: 429
      # JWT认证
      jwt-auth:
        key: user-key
        secret: my-secret-key
      # 链路追踪
      apache-apisix-logger:
        host: log-server
        port: 5044

  # 用户服务路由
  - id: user-service
    uri: /user/*
    upstream:
      type: roundrobin
      nodes:
        "user-service-1:8080": 1
        "user-service-2:8080": 1
    plugins:
      proxy-cache:
        cache_key:
          - uri
          - args
        cache_http_status:
          - 200
        cache_ttl: 60

# 全局插件
plugins:
  prometheus:
    enabled: true

3. 动态路由(Admin API)

# 添加路由
curl -X PUT http://127.0.0.1:9180/apisix/admin/routes/1 \
  -H "X-API-KEY: edd1c9f34a337a9f8ec4e6e4a6e0" \
  -H "Content-Type: application/json" \
  -d '{
    "uri": "/api/*",
    "upstream": {
      "type": "roundrobin",
      "nodes": {
        "127.0.0.1:8080": 1
      }
    },
    "plugins": {
      "limit-req": {
        "rate": 100,
        "burst": 50,
        "rejected_code": 503
      }
    }
  }'

4. 基于请求头的路由

-- 自定义路由逻辑
function route_by_header(conf, ctx)
    local version = ngx.req.get_headers()["X-Version"]
    local service_name = ctx.var.arg_service
    
    if version == "v2" then
        return "v2-backend"
    elseif version == "v1" then
        return "v1-backend"
    end
    
    return "default-backend"
end

5. 健康检查

upstreams:
  - id: order-service
    type: roundrobin
    checks:
      active:
        type: http
        http_path: /health
        healthy:
          interval: 2
          successes: 2
        unhealthy:
          interval: 1
          http_failures: 3
      passive:
        type: http
        healthy:
          successes: 3
        unhealthy:
          http_failures: 3
          tcp_failures: 3
    nodes:
      "order-service-1:8080": 100
      "order-service-2:8080": 100

四、网关选型对比

功能对比

特性 Kong APISIX Nginx
性能 最高
动态配置 支持 支持 需reload
插件生态 丰富 丰富 有限
学习成本
配置格式 Declarative YAML YAML/JSON Nginx conf
服务发现 Consul/Eureka Consul/Nacos upstream
限流 本地/Redis 本地/Redis 需扩展

Kong vs APISIX详细对比

维度 Kong APISIX
架构 PostgreSQL + Nginx etcd + Nginx
热更新 自动 自动
插件执行时机 可配置
日志格式 JSON JSON/CSV
Admin API RESTful RESTful
Dashboard 官方提供 官方提供

选型建议

选择Kong的场景:

  • 已有PostgreSQL基础设施
  • 需要成熟的插件生态
  • 团队熟悉Kong配置

选择APISIX的场景:

  • 需要更高的性能
  • 使用etcd作为配置中心
  • 需要更灵活的插件执行时机

选择Nginx的场景:

  • 简单的反向代理需求
  • 对性能要求极高
  • 不需要复杂的功能

五、生产最佳实践

1. 高可用部署

                    ┌─────────────┐
                    │   负载均衡  │
                    └──────┬──────┘
           ┌──────────────┼──────────────┐
           ▼              ▼              ▼
     ┌──────────┐  ┌──────────┐  ┌──────────┐
     │  Kong 1  │  │  Kong 2  │  │  Kong 3  │
     └────┬─────┘  └────┬─────┘  └────┬─────┘
           │             │             │
           └─────────────┼─────────────┘
                         ▼
               ┌─────────────────┐
               │   PostgreSQL     │
               │   (主从复制)     │
               └─────────────────┘

2. 安全配置

# Kong安全插件链
plugins:
  # 1. CORS跨域
  - name: cors
    
  # 2. IP黑名单
  - name: ip-restriction
    config:
      allow: ["10.0.0.0/8", "172.16.0.0/12"]
      deny: []
    
  # 3. 请求限流
  - name: rate-limiting
    config:
      second: 100
      policy: redis
    
  # 4. JWT认证
  - name: jwt
    
  # 5. 请求大小限制
  - name: request-size-limiting
    config:
      allowed: [10, "10kb"]

3. 监控配置

# Kong监控(Prometheus + Grafana)
plugins:
  - name: prometheus
    config:
      per_consumer: false

# Grafana Dashboard
- panels:
  - title: "Kong Request Rate"
    targets:
      - expr: sum(rate(kong_http_requests_total[5m])) by (service)
  
  - title: "Kong Latency"
    targets:
      - expr: histogram_quantile(0.99, rate(kong_latency_ms_bucket[5m]))

六、总结

API网关是微服务架构的核心组件:

  • 统一入口:简化客户端调用
  • 横切关注点:认证、限流、日志统一处理
  • 动态配置:无需重启即可更新路由和插件
  • 可观测性:完整的请求监控和链路追踪

选型建议:

  • 小规模场景:Nginx足够
  • 中等规模:Kong或APISIX
  • 大规模高性能需求:APISIX

思考题:你们的系统用的是什么API网关?有没有遇到过性能瓶颈?


个人观点,仅供参考

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐