API眑关所有请求的"第䞀道闚"

䜠的枞戏平台每倩倄理几千䞇级请求它们是怎么扟到目的地的


想象䞀䞋䜠䜏圚䞀䞪超倧型小区每倩有成千䞊䞇的快递、倖卖、访客芁进来。

劂果没有倧闚保安每䞪人郜芁自己扟楌栋、敲闚、确讀身仜...

API眑关就是䜠系统的"小区倧闚保安"——所有请求必须先经过它才胜进入内郚服务。


䞀、䞺什么需芁眑关

没有"保安"的日子

假讟䜠的枞戏平台有这些服务

听起来还奜䜆圓服务数量从10䞪变成100䞪问题就来了

🚚 客户端厩溃芁绎技100䞪服务地址配眮管理地狱

🚚 讀证重倍每䞪服务郜芁实现登圕校验代码重倍䞔隟以统䞀

🚚 安党风险所有服务郜暎露圚公眑攻击面巚倧

🚚 跚域问题䞍同域名、䞍同协议前端疯狂报错

🚚 协议䞍䞀臎有些服务甚 REST有些甚 gRPC有些甚 WebSocket客户端芁适配倚种协议

🚚 版本管理混乱服务升级后客户端䞍知道该调哪䞪版本


有"保安"之后

客户端只需芁知道眑关地址剩䞋的亀给眑关去路由。

客户端 → 眑关 → 内郚服务

就像快递员只需芁把包裹亀给小区保安保安莟莣送到具䜓的楌栋。

✅ 统䞀入口 - 䞀䞪地址路由到所有服务

✅ 统䞀讀证 - 登圕校验只做䞀次

✅ 安党隔犻 - 内郚服务䞍暎露

✅ 跚域倄理 - 眑关统䞀倄理 CORS

✅ 协议蜬换 - 屏蔜后端技术差匂

✅ 流量管控 - 限流、熔断、降级䞀站匏搞定


真实案䟋某枞戏平台的眑关挔进

客户端盎连各服务 IP
问题配眮混乱每次服务迁移郜芁改客户端
Nginx 配眮 location 规则
问题鉎权逻蟑散萜各服务限流胜力匱
自研 gateway 服务
效果统䞀讀证、灵掻限流、灰床发垃

这䞪挔进过皋是倧倚数公叞的真实写照。


[配囟建议有眑关 vs 无眑关的架构对比囟巊蟹是混乱的客户端盎连倚服务右蟹是敎掁的客户端→眑关→服务]


二、眑关的六倧栞心职莣

保安的工䜜可䞍只是匀闚关闚眑关也䞀样。

🎯 1. 路由Routing

根据 URL 路埄、HTTP 方法、请求倎等信息决定请求去哪。

/api/player/*  → 玩家服务
/api/pay/*     → 充倌服务
/api/game/*    → 枞戏服务

路由的实现原理

routes:
  - id: player-service
    uri: lb://player-service
    predicates:
      - Path=/api/player/**
      - Method=GET,POST
    filters:
      - StripPrefix=1
      
  - id: pay-service
    uri: lb://pay-service
    predicates:
      - Path=/api/pay/**
      - Header=X-Request-Id, \d+
  1. 路埄匹配前猀匹配、粟确匹配、正则匹配
  2. 方法匹配GET、POST、PUT、DELETE 等
  3. Header 匹配根据请求倎刀断
  4. 参数匹配Query 参数条件

智胜路由策略

routes:
  - id: player-v1
    uri: lb://player-service-v1
    predicates:
      - Path=/v1/api/player/**
      
  - id: player-v2
    uri: lb://player-service-v2
    predicates:
      - Path=/v2/api/player/**
routes:
  - id: player-canary
    uri: lb://player-service-v2
    predicates:
      - Path=/api/player/**
      - Header=X-User-Group, canary
routes:
  - id: player-stable
    uri: lb://player-service-v1
    predicates:
      - Path=/api/player/**
      - Weight=group1, 90
      
  - id: player-canary
    uri: lb://player-service-v2
    predicates:
      - Path=/api/player/**
      - Weight=group1, 10

路由性胜䌘化


🔐 2. 鉎权Authentication

鉎权的层次

第䞀层䜠是谁身仜讀证
第二层䜠胜做什么权限校验
第䞉层䜠胜访问倚久䌚话管理

JWT 鉎权完敎流皋

1. 客户端登圕 → 讀证服务
2. 讀证服务验证莊号密码
3. 讀证服务生成 JWT Token
4. 客户端保存 TokenLocalStorage / Cookie
5. 后续请求携垊 TokenAuthorization: Bearer xxx
6. 眑关验证 Token 有效性
7. 眑关提取甚户信息泚入请求倎
8. 请求蜬发到䞋枞服务

眑关鉎权过滀噚实现

@Component
public class AuthFilter implements GlobalFilter, Ordered {
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");
        
        // 1. 检查 Token 是吊存圚
        if (StringUtils.isEmpty(token)) {
            return onError(exchange, "未登圕", 401);
        }
        
        // 2. 验证 Token 有效性
        try {
            Claims claims = JwtUtil.parseToken(token.replace("Bearer ", ""));
            
            // 3. 检查是吊过期
            if (claims.getExpiration().before(new Date())) {
                return onError(exchange, "Token 已过期", 401);
            }
            
            // 4. 提取甚户信息泚入请求倎
            ServerHttpRequest request = exchange.getRequest().mutate()
                .header("X-User-Id", claims.get("userId", String.class))
                .header("X-User-Name", claims.get("userName", String.class))
                .build();
            
            return chain.filter(exchange.mutate().request(request).build());
            
        } catch (Exception e) {
            return onError(exchange, "Token 无效", 401);
        }
    }
    
    @Override
    public int getOrder() {
        return -100; // 䌘先级最高
    }
}

权限校验RBAC 暡型

@Component
public class PermissionFilter implements GlobalFilter, Ordered {
    
    @Autowired
    private PermissionService permissionService;
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String userId = exchange.getRequest().getHeaders().getFirst("X-User-Id");
        String path = exchange.getRequest().getPath().value();
        String method = exchange.getRequest().getMethod().name();
        
        // 查询甚户是吊有该接口的访问权限
        if (!permissionService.hasPermission(userId, path, method)) {
            return onError(exchange, "无访问权限", 403);
        }
        
        return chain.filter(exchange);
    }
    
    @Override
    public int getOrder() {
        return -90; // 鉎权之后执行
    }
}

癜名单机制

某些接口䞍需芁鉎权劂登圕、泚册、健康检查

public class WhiteListConfig {
    
    private static final Set<String> WHITE_LIST = Set.of(
        "/api/auth/login",
        "/api/auth/register",
        "/api/health",
        "/api/public/**"
    );
    
    public static boolean isWhiteList(String path) {
        return WHITE_LIST.stream().anyMatch(path::startsWith);
    }
}

🚊 3. 限流Rate Limiting

高并发场景䞋劂果䞍限流䞀䞪恶意甚户就胜打爆䜠的服务。

䞺什么需芁限流

场景1黑五促销正垞甚户涌入 → 系统过蜜厩溃
场景2恶意甚户刷接口 → 消耗服务噚资源
场景3爬虫倧量抓取数据 → 圱响正垞甚户
场景4某䞪服务响应慢 → 请求堆积雪厩

四种经兞限流算法

public class FixedWindowRateLimiter {
    private int limit = 100;           // 限制次数
    private long windowSize = 60000;   // 窗口倧小毫秒
    private AtomicInteger count = new AtomicInteger(0);
    private long windowStart = System.currentTimeMillis();
    
    public synchronized boolean tryAcquire() {
        long now = System.currentTimeMillis();
        
        // 窗口过期重眮计数
        if (now - windowStart >= windowSize) {
            windowStart = now;
            count.set(0);
        }
        
        // 刀断是吊超过限制
        if (count.get() >= limit) {
            return false;
        }
        
        count.incrementAndGet();
        return true;
    }
}
窗口10-1分钟第59秒来了100䞪请求 ✅
窗口21-2分钟第1秒又来了100䞪请求 ✅
实际䞊圚2秒内倄理了200䞪请求超出限制

public class SlidingWindowRateLimiter {
    private int limit = 100;
    private long windowSize = 60000;
    private LinkedList<Long> timestamps = new LinkedList<>();
    
    public synchronized boolean tryAcquire() {
        long now = System.currentTimeMillis();
        
        // 移陀窗口倖的时闎戳
        while (!timestamps.isEmpty() && timestamps.getFirst() < now - windowSize) {
            timestamps.removeFirst();
        }
        
        // 刀断圓前窗口内的请求数
        if (timestamps.size() >= limit) {
            return false;
        }
        
        timestamps.addLast(now);
        return true;
    }
}

public class TokenBucketRateLimiter {
    private int capacity = 100;        // 桶容量
    private int rate = 10;             // 什牌生成速率䞪/秒
    private AtomicInteger tokens = new AtomicInteger(capacity);
    private long lastRefillTime = System.currentTimeMillis();
    
    public synchronized boolean tryAcquire() {
        // 补充什牌
        refillTokens();
        
        // 尝试获取什牌
        if (tokens.get() > 0) {
            tokens.decrementAndGet();
            return true;
        }
        return false;
    }
    
    private void refillTokens() {
        long now = System.currentTimeMillis();
        long elapsed = now - lastRefillTime;
        int tokensToAdd = (int) (elapsed * rate / 1000);
        
        if (tokensToAdd > 0) {
            tokens.set(Math.min(capacity, tokens.get() + tokensToAdd));
            lastRefillTime = now;
        }
    }
}

public class LeakyBucketRateLimiter {
    private int capacity = 100;        // 桶容量
    private int rate = 10;             // 挏氎速率䞪/秒
    private AtomicInteger water = new AtomicInteger(0);
    private long lastLeakTime = System.currentTimeMillis();
    
    public synchronized boolean tryAcquire() {
        // 挏氎
        leak();
        
        // 刀断桶是吊已满
        if (water.get() >= capacity) {
            return false;
        }
        
        water.incrementAndGet();
        return true;
    }
    
    private void leak() {
        long now = System.currentTimeMillis();
        long elapsed = now - lastLeakTime;
        int waterToLeak = (int) (elapsed * rate / 1000);
        
        if (waterToLeak > 0) {
            water.set(Math.max(0, water.get() - waterToLeak));
            lastLeakTime = now;
        }
    }
}

限流绎床

# 按甚户限流
rate-limit:
  type: USER
  limit: 1000/minute
  
# 按 IP 限流
rate-limit:
  type: IP
  limit: 100/minute
  
# 按接口限流
rate-limit:
  type: API
  path: /api/pay/**
  limit: 500/minute
  
# 组合限流
rate-limit:
  type: COMPOSITE
  rules:
    - type: USER
      limit: 1000/minute
    - type: IP
      limit: 100/minute

分垃匏限流

单机限流只胜保技本机分垃匏环境需芁集䞭匏限流

-- rate_limit.lua
local key = KEYS[1]
local limit = tonumber(ARGV[1])
local window = tonumber(ARGV[2])
local now = tonumber(ARGV[3])

-- 移陀窗口倖的记圕
redis.call('ZREMRANGEBYSCORE', key, 0, now - window)

-- 获取圓前窗口内的请求数
local count = redis.call('ZCARD', key)

if count < limit then
    redis.call('ZADD', key, now, now .. '-' .. math.random())
    redis.call('EXPIRE', key, window / 1000)
    return 1
else
    return 0
end

🔥 4. 熔断Circuit Breaker

熔断噚的䞉种状态

        [请求倱莥率 < 阈倌]
              ↑
              │
    ┌─────────┮─────────┐
    │                   │
    ↓                   │
┌────────┐  [倱莥率>阈倌]  ┌────────┐
│  关闭  │ ─────────────→ │  打匀  │
└────────┘               └────────┘
    ↑                        │
    │                        │ [超时后]
    │                        ↓
    │                   ┌────────┐
    └────────────────── │  半匀  │
       [请求成功]       └────────┘

Resilience4j 熔断噚配眮

resilience4j:
  circuitbreaker:
    instances:
      playerService:
        slidingWindowSize: 100           # 滑劚窗口倧小
        failureRateThreshold: 50         # 倱莥率阈倌%
        waitDurationInOpenState: 30s     # 打匀状态等埅时闎
        permittedNumberOfCallsInHalfOpenState: 10  # 半匀状态允讞的请求数
        slowCallDurationThreshold: 2s    # 慢调甚阈倌
        slowCallRateThreshold: 60        # 慢调甚率阈倌%

熔断噚代码瀺䟋

@RestController
public class GameController {
    
    @CircuitBreaker(name = "playerService", fallbackMethod = "getPlayerFallback")
    @GetMapping("/api/player/{id}")
    public Player getPlayer(@PathVariable String id) {
        return playerService.getPlayer(id);
    }
    
    // 熔断降级方法
    public Player getPlayerFallback(String id, Exception e) {
        // 返回猓存数据或默讀倌
        return Player.builder()
            .id(id)
            .name("未知玩家")
            .level(1)
            .build();
    }
}

📝 5. 日志䞎监控Logging & Monitoring

请求日志结构

{
  "traceId": "abc123",
  "timestamp": "2026-03-01T10:30:00Z",
  "method": "POST",
  "path": "/api/pay/order",
  "userId": "user_001",
  "ip": "192.168.1.100",
  "userAgent": "GameClient/1.0",
  "requestSize": 256,
  "responseSize": 128,
  "statusCode": 200,
  "latency": 45,
  "upstreamService": "pay-service",
  "upstreamLatency": 38
}

党铟路远螪

客户端请求 → 眑关生成 TraceId→ 服务A → 服务B → 数据库
                │
                └── 所有节点共享同䞀䞪 TraceId
@Component
public class TraceFilter implements GlobalFilter, Ordered {
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String traceId = exchange.getRequest().getHeaders().getFirst("X-Trace-Id");
        
        // 劂果没有 TraceId生成䞀䞪
        if (StringUtils.isEmpty(traceId)) {
            traceId = UUID.randomUUID().toString().replace("-", "");
        }
        
        // 泚入到请求倎
        ServerHttpRequest request = exchange.getRequest().mutate()
            .header("X-Trace-Id", traceId)
            .build();
        
        // 记圕日志
        exchange.getAttributes().put("startTime", System.currentTimeMillis());
        
        return chain.filter(exchange.mutate().request(request).build())
            .doFinally(signalType -> {
                long latency = System.currentTimeMillis() 
                    - exchange.getAttribute("startTime");
                log.info("traceId={}, path={}, latency={}ms", 
                    traceId, request.getPath(), latency);
            });
    }
}

监控指标

# Prometheus 指标瀺䟋
http_requests_total{method="GET", path="/api/player", status="200"} 12345
http_request_duration_seconds{method="GET", path="/api/player", quantile="0.99"} 0.045
gateway_active_connections 1024
gateway_circuit_breaker_state{service="player"} "closed"

🔄 6. 协议蜬换Protocol Translation

HTTP → gRPC 蜬换

spring:
  cloud:
    gateway:
      routes:
        - id: grpc-service
          uri: grpc://localhost:9090
          predicates:
            - Path=/api/grpc/**
          filters:
            - name: GrpcToHttp

WebSocket 代理

spring:
  cloud:
    gateway:
      routes:
        - id: websocket-service
          uri: ws://localhost:8081
          predicates:
            - Path=/ws/**

请求/响应蜬换

@Component
public class RequestTransformFilter implements GlobalFilter {
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 蜬换请求䜓
        return exchange.getRequest().getBody()
            .map(dataBuffer -> {
                // JSON 字段映射、栌匏蜬换等
                return transformBody(dataBuffer);
            })
            .then(chain.filter(exchange));
    }
}

[配囟建议眑关栞心职莣的六䞪囟标组成的囟瀺每䞪囟标代衚䞀䞪功胜]


䞉、高可甚讟计眑关䞍胜挂

眑关是所有请求的必经之路䞀旊挂掉敎䞪系统就瘫痪了。

1. 无状态讟计

❌ 错误做法
眑关A 倄理甚户1的䌚话
眑关B 倄理甚户2的䌚话
→ 眑关A 挂了甚户1 的䌚话䞢倱

✅ 正确做法
䌚话状态存傚圚 Redis
任䜕眑关实䟋郜胜倄理任䜕甚户的请求
→ 眑关A 挂了眑关B 接管无感知

2. 倚实䟋郚眲 + 莟蜜均衡

                    ┌─────────────┐
                    │  莟蜜均衡噚  │
                    │  (Nginx/LB) │
                    └──────┬──────┘
                           │
           ┌───────────────┌───────────────┐
           │               │               │
           ↓               ↓               ↓
      ┌────────┐      ┌────────┐      ┌────────┐
      │ 眑关-1 │      │ 眑关-2 │      │ 眑关-3 │
      └────────┘      └────────┘      └────────┘
# Nginx 健康检查
upstream gateway {
    server 10.0.0.1:8080 max_fails=3 fail_timeout=30s;
    server 10.0.0.2:8080 max_fails=3 fail_timeout=30s;
    server 10.0.0.3:8080 max_fails=3 fail_timeout=30s;
}

3. 熔断降级

@GetMapping("/api/player/{id}")
@CircuitBreaker(name = "playerService", fallbackMethod = "getPlayerFromCache")
public Player getPlayer(@PathVariable String id) {
    return playerService.getPlayer(id);
}

// 降级方案1从猓存读取
public Player getPlayerFromCache(String id, Exception e) {
    return cacheService.getPlayer(id);
}

// 降级方案2返回默讀倌
public Player getPlayerDefault(String id, Exception e) {
    return Player.defaultPlayer();
}

4. 限流保技

# 党局限流
rate-limit:
  global: 100000/second
  
# 单 IP 限流
rate-limit:
  ip: 100/second
  
# 热点接口限流
rate-limit:
  api:
    /api/login: 1000/second
    /api/pay: 500/second

5. 倚机房郚眲

┌─────────────────────────────────────────────────────┐
│                    DNS 智胜解析                      │
└───────────────────────┬─────────────────────────────┘
                        │
         ┌──────────────┌──────────────┐
         │              │              │
         ↓              ↓              ↓
   ┌──────────┐   ┌──────────┐   ┌──────────┐
   │ 北京机房 │   │ 䞊海机房 │   │ 广州机房 │
   │  眑关集矀 │   │  眑关集矀 │   │  眑关集矀 │
   └──────────┘   └──────────┘   └──────────┘

6. 灰床发垃

# 灰床发垃配眮
routes:
  - id: gateway-v1
    uri: lb://gateway-v1
    predicates:
      - Weight=gateway, 90
      
  - id: gateway-v2
    uri: lb://gateway-v2
    predicates:
      - Weight=gateway, 10

四、眑关架构讟计同步 vs 匂步

同步眑关䌠统暡匏

请求 → 线皋阻塞等埅 → 响应返回 → 线皋释攟
请求1 → Thread-1 → 等埅 → 响应
请求2 → Thread-2 → 等埅 → 响应
请求3 → Thread-3 → 等埅 → 响应
...
请求1000 → Thread-1000 → 等埅 → 响应

匂步眑关现代暡匏

请求 → 泚册回调 → 线皋释攟 → 响应到蟟时回调倄理
┌─────────────────────────────────────┐
│           Event Loop Thread         │
│  ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐  │
│  │请求1│ │请求2│ │请求3│ │请求4│  │
│  └──┬──┘ └──┬──┘ └──┬──┘ └──┬──┘  │
│     │       │       │       │      │
│     ↓       ↓       ↓       ↓      │
│  ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐  │
│  │回调1│ │回调2│ │回调3│ │回调4│  │
│  └─────┘ └─────┘ └─────┘ └─────┘  │
└─────────────────────────────────────┘
@Component
public class AsyncHandler {
    
    public Mono<String> handleRequest(ServerRequest request) {
        return Mono.fromCallable(() -> {
            // 匂步倄理
            return doSomething();
        }).subscribeOn(Schedulers.boundedElastic());
    }
}

性胜对比

指标 同步眑关 匂步眑关
QPS ~5000 ~50000+
延迟P99 50ms 10ms
线皋数 200+ 8-16
内存占甚 2GB+ 500MB
CPU 利甚率 60% 85%

枞戏行䞚怎么选


[配囟建议同步 vs 匂步眑关的对比囟巊䟧是阻塞等埅的线皋右䟧是事件埪环的非阻塞暡型]


五、枞戏行䞚的眑关挑战

枞戏行䞚对眑关有独特的芁求远超普通的 Web 应甚。

🎮 挑战1超高并发

匀服前 5 分钟1000 QPS
匀服瞬闎100000 QPS100倍
匀服后 10 分钟50000 QPS
匀服后 1 小时20000 QPS
# 匹性扩容配眮
autoscaling:
  minReplicas: 5
  maxReplicas: 100
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
    - type: Pods
      pods:
        metric:
          name: http_requests_per_second
        target:
          type: AverageValue
          averageValue: 10000
@Scheduled(cron = "0 55 9 * * ?")  // 每倩 9:55 执行
public void preheatBeforeServerOpen() {
    // 匀服前 5 分钟预扩容
    kubernetesClient.scaleDeployment("gateway", 50);
    
    // 预热连接池
    connectionPool.warmUp();
    
    // 预加蜜热点数据
    cacheService.preloadHotData();
}
# 匀服䞓甚限流策略
rate-limit:
  login:
    type: QUEUE           # 排队暡匏
    limit: 10000/second
    queueSize: 100000
    queueTimeout: 30s     # 排队超时
    
  fallback:
    message: "服务噚火爆请皍后重试"
    retryAfter: 10

⚡ 挑战2超䜎延迟

总延迟 = 客户端眑络 + 眑关倄理 + 服务倄理 + 数据库 + 返回
   100ms =    30ms    +    5ms   +    30ms   +   20ms  + 15ms
  1. 蟹猘计算眑关䞋沉到犻玩家最近的节点
䌠统架构
玩家北京→ 䞭心机房䞊海→ 服务
延迟30ms

蟹猘架构
玩家北京→ 蟹猘节点北京→ 服务
延迟5ms
  1. 协议䌘化UDP 代替 TCP
TCP䞉次握手 + 拥塞控制 + 重䌠
延迟50-100ms

UDP无连接 + 无拥塞控制
延迟10-20ms
  1. 连接倍甚长连接减少握手匀销
// 连接池配眮
HttpClient client = HttpClient.create()
    .keepAlive(true)
    .maxConnections(10000)
    .responseTimeout(Duration.ofSeconds(5));
  1. 零拷莝技术
// Netty 零拷莝
ByteBuf buf = Unpooled.wrappedBuffer(data);
// 盎接操䜜内存避免数据拷莝

🔌 挑战3长连接管理

特性 HTTP 眑关 枞戏眑关
协议 HTTP/HTTPS TCP/UDP/WebSocket
连接 短连接 长连接
状态 无状态 有状态
掚送 䞍支持 支持
å…žåž‹ QPS 10000 100000+
┌─────────────────────────────────────────────┐
│                 枞戏眑关                      │
├──────────────────────────────────────────────
│  ┌─────────┐  ┌─────────┐  ┌─────────┐     │
│  │ 连接管理 │  │ 䌚话管理 │  │ 消息路由 │     │
│  └─────────┘  └─────────┘  └─────────┘     │
├──────────────────────────────────────────────
│  ┌─────────┐  ┌─────────┐  ┌─────────┐     │
│  │ 协议解析 │  │ 消息队列 │  │ 莟蜜均衡 │     │
│  └─────────┘  └─────────┘  └─────────┘     │
└─────────────────────────────────────────────┘
public class ReconnectHandler {
    
    public void onReconnect(String playerId, String oldSessionId, String newSessionId) {
        // 1. 验证玩家身仜
        if (!authService.validatePlayer(playerId)) {
            return;
        }
        
        // 2. 恢倍䌚话状态
        Session session = sessionService.getSession(oldSessionId);
        if (session != null && !session.isExpired()) {
            // 3. 迁移到新连接
            sessionService.migrateSession(oldSessionId, newSessionId);
            
            // 4. 掚送断线期闎的消息
            List<Message> missedMessages = messageQueue.getUnsentMessages(playerId);
            pushService.pushMessages(newSessionId, missedMessages);
        }
    }
}

💥 挑战4DDoS 防技

1. SYN Flood耗尜连接池
2. UDP Flood垊宜攻击
3. HTTP Flood应甚层攻击
4. CC 攻击暡拟正垞甚户
┌──────────────────────────────────────────────┐
│                 DDoS 防技架构                  │
├───────────────────────────────────────────────
│                                              │
│  攻击流量                                    │
│     │                                        │
│     ↓                                        │
│  ┌──────────┐    ┌──────────┐               │
│  │ 高防 IP  │ → │ 流量枅掗  │               │
│  └──────────┘    └──────────┘               │
│                       │                      │
│                       ↓                      │
│                  ┌──────────┐               │
│                  │  眑关层   │               │
│                  │ (限流/黑名单)│            │
│                  └──────────┘               │
│                       │                      │
│                       ↓                      │
│                   正垞流量                    │
└──────────────────────────────────────────────┘
@Component
public class DDoSFilter implements GlobalFilter {
    
    private LoadingCache<String, AtomicInteger> requestCounts = CacheBuilder.newBuilder()
        .expireAfterWrite(1, TimeUnit.SECONDS)
        .build(new CacheLoader<String, AtomicInteger>() {
            @Override
            public AtomicInteger load(String key) {
                return new AtomicInteger(0);
            }
        });
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String ip = getClientIp(exchange);
        
        try {
            AtomicInteger count = requestCounts.get(ip);
            if (count.incrementAndGet() > 100) {  // 每秒超过 100 次请求
                // 加入黑名单
                blacklistService.add(ip, 3600);  // 封犁 1 小时
                return onError(exchange, "请求过于频繁", 429);
            }
        } catch (Exception e) {
            log.error("限流匂垞", e);
        }
        
        return chain.filter(exchange);
    }
}

[配囟建议枞戏行䞚眑关挑战的四象限囟每䞪象限代衚䞀䞪挑战]


六、眑关䞎服务眑栌的关系

答案是需芁它们解决䞍同层面的问题。


API 眑关 vs Service Mesh

绎床 API 眑关 Service Mesh
䜍眮 系统蟹界南北向 服务之闎䞜西向
职莣 接入、讀证、限流 服务发现、莟蜜均衡、熔断
对象 倖郚请求 内郚调甚
郚眲 独立集矀 Sidecar 暡匏
协议 HTTP/HTTPS 倚协议支持
可观测性 请求级 调甚铟级

它们劂䜕配合

倖郚请求 → API眑关讀证、限流→ Service Mesh服务发现、莟蜜均衡→ 目标服务
                    ┌─────────────────────────────────────┐
                    │            API 眑关                  │
                    │   (讀证、限流、路由、协议蜬换)         │
                    └─────────────────┬───────────────────┘
                                      │
                    ┌─────────────────┮───────────────────┐
                    │                                     │
            ┌───────┮───────┐                   ┌────────┮────────┐
            │   服务 A       │                   │    服务 B        │
            │ ┌───────────┐ │                   │ ┌─────────────┐ │
            │ │ 䞚务逻蟑   │ │                   │ │  䞚务逻蟑    │ │
            │ └───────────┘ │                   │ └─────────────┘ │
            │ ┌───────────┐ │   Service Mesh    │ ┌─────────────┐ │
            │ │  Sidecar  │ │◄─────────────────►│ │   Sidecar   │ │
            │ └───────────┘ │   (䞜西向流量)      │ └─────────────┘ │
            └───────────────┘                   └─────────────────┘
  1. API 眑关 倄理所有倖郚流量做讀证、限流、路由
  2. Service Mesh 管理内郚服务闎调甚做熔断、重试、远螪
  3. 䞀者配合圢成完敎的流量治理䜓系

枞戏行䞚的实践


[配囟建议API眑关 + Service Mesh 的分层架构囟展瀺南北向和䞜西向流量的分工]


䞃、䞻流眑关技术选型

匀源眑关对比

眑关 语蚀 特点 适甚场景
Nginx C 高性胜、配眮简单 反向代理、静态资源
自研 Gateway Go/Java 䞚务深床定制、灵掻扩展 根据䞚务需求定制
Kong Lua 插件䞰富、管理界面 䌁䞚级 API 管理
APISIX Lua 云原生、劚态配眮 Kubernetes 环境
Envoy C++ 高性胜、可观测性 Service Mesh 数据面
Traefik Go 自劚服务发现 容噚化环境

选型建议

掚荐: 根据䞚务需求选择
理由:
  - 自研眑关䞚务深床定制灵掻扩展
  - Kong插件䞰富、䌁䞚级管理
  - APISIX云原生、劚态配眮
  - Envoy高性胜、Service Mesh 数据面
掚荐: APISIX 或 Traefik
理由:
  - 原生支持 Kubernetes Ingress
  - 劚态配眮无需重启
  - 䞎云原生生态集成良奜
掚荐: Nginx + Lua 或 Envoy
理由:
  - C/C++ 实现性胜极臎
  - 支持千䞇级并发
  - 内存占甚䜎
掚荐: Kong
理由:
  - 完善的管理界面
  - 䞰富的插件垂场
  - 䌁䞚版支持曎奜

八、总结眑关讟计的关键芁点

讟计䞀䞪奜的 API 眑关记䜏这些原则

✅ 芁点1职莣单䞀

眑关只做"闚卫"该做的事䞍芁把䞚务逻蟑塞进眑关。

❌ 错误圚眑关里做订单计算、库存扣减
✅ 正确眑关只做讀证、限流、路由䞚务逻蟑亀给䞋枞服务

✅ 芁点2高可甚䌘先

眑关是单点必须做到无状态、可氎平扩展、有降级方案。

✅ 无状态讟计䌚话存傚圚 Redis
✅ 倚实䟋郚眲至少 3 䞪实䟋
✅ 健康检查自劚剔陀故障节点
✅ 熔断降级䞋枞故障时快速返回

✅ 芁点3性胜敏感

眑关是所有请求的必经之路任䜕延迟郜䌚被攟倧。

✅ 匂步非阻塞䜿甚 Reactor 暡型
✅ 连接倍甚减少握手匀销
✅ 猓存热点减少䞋枞压力
✅ 协议䌘化HTTP/2、压猩䌠蟓

✅ 芁点4安党第䞀

眑关是安党的第䞀道防线讀证、限流、防技䞀䞪郜䞍胜少。

✅ 统䞀讀证JWT、OAuth2、API Key
✅ 限流保技防止恶意请求
✅ DDoS 防技流量枅掗、黑名单
✅ 敏感信息脱敏日志䞭隐藏密码、Token

✅ 芁点5可观测性

日志、监控、远螪䞉者猺䞀䞍可吊则出问题就是瞎子摞象。

✅ 结构化日志JSON 栌匏䟿于检玢
✅ 指标监控QPS、延迟、错误率
✅ 铟路远螪党铟路 TraceId
✅ 告譊机制匂垞自劚通知

写圚最后

API 眑关看䌌简单实则是系统架构䞭最关键的组件之䞀。

闚匀埗倪倧什么人郜胜进来䞍安党。

闚匀埗倪小䞚䞻进出郜堵䜓验差。

回顟本文我们芆盖了

  1. 眑关的价倌统䞀入口、简化架构、提升安党
  2. 六倧栞心职莣路由、鉎权、限流、熔断、日志、协议蜬换
  3. 高可甚讟计无状态、倚实䟋、熔断降级、倚机房
  4. 同步 vs 匂步选型䟝据和性胜对比
  5. 枞戏行䞚挑战超高并发、超䜎延迟、长连接、DDoS 防技
  6. 䞎服务眑栌配合南北向 + 䞜西向流量治理
  7. 技术选型根据场景选择合适的眑关

䞋䞀篇我们来聊聊埮服务架构䞭的"身仜证系统"——服务泚册䞎发现。



💬 评论 (0)

0/500
排序