API 网关实战教程 — 微服务入口

适用人群:后端开发者、架构师
学习时长:约2-3天
技术:Nginx / Kong / Spring Cloud Gateway
适用场景:微服务架构、API管理

一、API网关是什么?

API网关是系统的统一入口,负责请求路由、认证、限流、日志等横切关注点。

功能说明
路由转发将请求转发到对应的后端服务
负载均衡将流量分发到多个服务实例
认证授权统一身份验证
限流熔断保护后端服务
日志监控记录请求日志
协议转换HTTP ↔ gRPC
缓存缓存热点数据

二、Nginx 作为API网关

2.1 基础配置

# 定义上游服务
upstream user-service {
    server 192.168.1.10:8081;
    server 192.168.1.11:8081;
}

upstream order-service {
    server 192.168.1.20:8082;
    server 192.168.1.21:8082;
}

upstream product-service {
    server 192.168.1.30:8083;
}

# 限流配置
limit_req_zone $binary_remote_addr zone=api:10m rate=100r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;

server {
    listen 80;
    server_name api.example.com;
    
    # 全局限流
    limit_req zone=api burst=200 nodelay;
    
    # 用户服务
    location /api/users/ {
        proxy_pass http://user-service;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Request-ID $request_id;
    }
    
    # 订单服务
    location /api/orders/ {
        proxy_pass http://order-service;
        proxy_set_header X-Real-IP $remote_addr;
    }
    
    # 商品服务
    location /api/products/ {
        proxy_pass http://product-service;
        proxy_set_header X-Real-IP $remote_addr;
    }
    
    # 登录接口限流(更严格)
    location /api/auth/login {
        limit_req zone=login burst=3 nodelay;
        proxy_pass http://user-service;
    }
}

2.2 负载均衡策略

# 轮询(默认)
upstream backend {
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}

# 加权轮询
upstream backend {
    server 192.168.1.10:8080 weight=3;
    server 192.168.1.11:8080 weight=2;
}

# IP Hash(会话保持)
upstream backend {
    ip_hash;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}

# 最少连接
upstream backend {
    least_conn;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}


三、Kong API网关

3.1 安装

# Docker安装
docker run -d --name kong-database \
  -p 5432:5432 \
  -e KONG_DATABASE=postgres \
  -e KONG_PG_PASSWORD=kong \
  postgres:13

docker run --rm --network=host \
  kong:latest kong migrations bootstrap

docker run -d --name kong \
  --network=host \
  -e KONG_DATABASE=postgres \
  -e KONG_PG_HOST=localhost \
  -e KONG_PG_PASSWORD=kong \
  -e KONG_PROXY_LISTEN=0.0.0.0:8000 \
  -e KONG_ADMIN_LISTEN=0.0.0.0:8001 \
  kong:latest

3.2 配置服务和路由

# 添加服务
curl -X POST http://localhost:8001/services/ \
  --data "name=user-service" \
  --data "url=http://192.168.1.10:8081"

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

# 添加限流插件
curl -X POST http://localhost:8001/services/user-service/plugins \
  --data "name=rate-limiting" \
  --data "config.second=100" \
  --data "config.policy=local"

# 添加认证插件
curl -X POST http://localhost:8001/services/user-service/plugins \
  --data "name=jwt"


四、Spring Cloud Gateway(Java)

# application.yml
spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/api/users/**
          filters:
            - StripPrefix=0
            
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/api/orders/**
          filters:
            - StripPrefix=0
            
        - id: product-service
          uri: lb://product-service
          predicates:
            - Path=/api/products/**
          filters:
            - StripPrefix=0
      
      default-filters:
        - name: RequestRateLimiter
          args:
            redis-rate-limiter.replenishRate: 100
            redis-rate-limiter.burstCapacity: 200

// 自定义认证过滤器
@Component
public class AuthGatewayFilter implements GatewayFilterFactory<AuthGatewayFilter.Config> {
    
    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            String token = exchange.getRequest().getHeaders().getFirst("Authorization");
            
            if (token == null || !token.startsWith("Bearer ")) {
                exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                return exchange.getResponse().setComplete();
            }
            
            // 验证token
            try {
                // JWT验证逻辑
                String userId = verifyToken(token.substring(7));
                
                // 将用户信息添加到请求头
                ServerHttpRequest request = exchange.getRequest().mutate()
                    .header("X-User-Id", userId)
                    .build();
                
                return chain.filter(exchange.mutate().request(request).build());
            } catch (Exception e) {
                exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                return exchange.getResponse().setComplete();
            }
        };
    }
    
    @Override
    public Class<Config> getConfigClass() {
        return Config.class;
    }
    
    public static class Config {
        // 配置属性
    }
}


五、网关安全

5.1 JWT认证

# Nginx + Lua实现JWT验证
location /api/ {
    access_by_lua_block {
        local jwt = require "resty.jwt"
        local auth_header = ngx.req.get_headers()["Authorization"]
        
        if not auth_header then
            ngx.status = 401
            ngx.say('{"code": 401, "message": "未登录"}')
            return ngx.exit(401)
        end
        
        local token = string.match(auth_header, "Bearer%s+(.+)")
        local jwt_obj = jwt:verify("your-secret-key", token)
        
        if not jwt_obj.verified then
            ngx.status = 401
            ngx.say('{"code": 401, "message": "token无效"}')
            return ngx.exit(401)
        end
        
        ngx.req.set_header("X-User-Id", jwt_obj.payload.sub)
    }
    
    proxy_pass http://backend;
}

5.2 CORS配置

# Nginx CORS配置
location /api/ {
    # CORS头
    add_header 'Access-Control-Allow-Origin' '*' always;
    add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
    add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always;
    
    # 预检请求
    if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization';
        add_header 'Access-Control-Max-Age' 1728000;
        add_header 'Content-Type' 'text/plain charset=UTF-8';
        add_header 'Content-Length' 0;
        return 204;
    }
    
    proxy_pass http://backend;
}


六、监控与日志

# 自定义日志格式
log_format gateway '$remote_addr - $remote_user [$time_local] '
                   '"$request" $status $body_bytes_sent '
                   '"$http_referer" "$http_user_agent" '
                   '$request_time $upstream_response_time '
                   '$request_id';

access_log /var/log/nginx/gateway.log gateway;


学习建议

  1. 先用Nginx实现基本网关,理解核心概念
  2. 学习Kong或APISIX,生产级网关
  3. 掌握认证和限流,安全是核心
  4. 配置监控和日志,可观测性很重要
  5. 理解服务发现,动态路由

下一步学习

返回首页