API网关架构设计实战:限流熔断与动态路由策略

API网关在微服务架构中承担统一入口、请求路由、限流熔断等核心职责,是后端开发中服务治理的关键基础设施。相比客户端直连各微服务,API网关屏蔽了内部服务拓扑,提供统一的鉴权、监控和流量控制能力,在高并发设计和业务中台建设中扮演枢纽角色。

API网关核心功能与技术选型

主流API网关方案包括Spring Cloud Gateway(Java生态)、Kong(Lua/Nginx)、APISIX(Lua/Nginx)和Envoy(C++)。Spring Cloud Gateway基于WebFlux响应式模型,与Spring Boot生态无缝集成,适合Java技术栈团队:

// Spring Cloud Gateway 基础配置
// application.yml
spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/api/users/**
          filters:
            - StripPrefix=2
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 100
                redis-rate-limiter.burstCapacity: 200
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/api/orders/**
          filters:
            - StripPrefix=2

lb://前缀表示使用负载均衡发现服务实例,StripPrefix=2去掉URL前两级路径(/api/users -> /)。RequestRateLimiter基于Redis实现令牌桶限流,replenishRate为令牌填充速率(100/秒),burstCapacity为桶容量(200)。

限流策略设计与多维度限流实现

单一维度的限流无法满足复杂业务场景。API网关需要支持按API、按用户、按IP等多维度限流。通过自定义GatewayFilter实现多维度限流:

@Component
public class MultiDimensionRateLimiterFilter implements GlobalFilter, Ordered {
    
    @Autowired
    private StringRedisTemplate redis;
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String apiPath = exchange.getRequest().getPath().value();
        String clientIp = getClientIp(exchange);
        String userId = getUserId(exchange);
        
        // API级别限流: 每个API 1000 QPS
        if (!tryAcquire("rate:api:" + apiPath, 1000, 1)) {
            return rateLimitResponse(exchange, "API限流");
        }
        
        // 用户级别限流: 每个用户 100 QPS
        if (userId != null && !tryAcquire("rate:user:" + userId, 100, 1)) {
            return rateLimitResponse(exchange, "用户限流");
        }
        
        // IP级别限流: 防刷
        if (!tryAcquire("rate:ip:" + clientIp, 50, 1)) {
            return rateLimitResponse(exchange, "IP限流");
        }
        
        return chain.filter(exchange);
    }
    
    private boolean tryAcquire(String key, int limit, int windowSec) {
        // Redis滑动窗口限流
        long now = System.currentTimeMillis();
        long windowStart = now - windowSec * 1000L;
        redis.opsForZSet().removeRangeByScore(key, 0, windowStart);
        Long count = redis.opsForZSet().zCard(key);
        if (count != null && count >= limit) {
            return false;
        }
        redis.opsForZSet().add(key, now + ":" + Math.random(), now);
        redis.expire(key, windowSec + 1, TimeUnit.SECONDS);
        return true;
    }
    
    @Override
    public int getOrder() { return -100; }
}

滑动窗口限流比固定窗口更精确,避免了窗口边界处的突发流量问题。Redis ZSet的score存储时间戳,通过ZREMRANGEBYSCORE清理过期记录,ZCARD统计窗口内请求数。这种方案在Redis单节点下可支撑10万QPS级别的限流判断。

熔断降级机制与Sentinel集成

限流保护网关自身,熔断保护下游服务。当某个下游服务持续超时或报错时,熔断器打开,快速失败而非等待超时,防止故障扩散。集成Sentinel实现熔断降级:

// 自定义熔断降级过滤器
@Component
public class CircuitBreakerFilter implements GlobalFilter {
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String serviceId = getServiceId(exchange);
        
        return chain.filter(exchange)
            .timeout(Duration.ofSeconds(3))  // 超时3秒
            .onErrorResume(ex -> {
                if (ex instanceof TimeoutException) {
                    // 记录超时次数,达到阈值触发熔断
                    circuitBreakerRegistry.recordFailure(serviceId);
                    return fallbackResponse(exchange, "服务超时,请稍后重试");
                }
                return Mono.error(ex);
            });
    }
}

// 熔断器状态管理
@Service
public class CircuitBreakerRegistry {
    private Map<String, CircuitBreakerState> breakers = new ConcurrentHashMap<>();
    
    public boolean isAllowed(String serviceId) {
        CircuitBreakerState state = breakers.computeIfAbsent(
            serviceId, k -> new CircuitBreakerState()
        );
        return state.allowRequest();
    }
    
    public void recordFailure(String serviceId) {
        CircuitBreakerState state = breakers.get(serviceId);
        if (state != null) state.recordFailure();
    }
}

class CircuitBreakerState {
    private AtomicInteger failures = new AtomicInteger(0);
    private volatile long lastFailureTime = 0;
    private static final int THRESHOLD = 5;
    private static final long RECOVERY_TIMEOUT = 30000; // 30秒半开尝试
    
    boolean allowRequest() {
        if (failures.get() < THRESHOLD) return true;
        // 熔断状态,检查是否到半开时间
        if (System.currentTimeMillis() - lastFailureTime > RECOVERY_TIMEOUT) {
            failures.set(0);  // 重置,进入半开
            return true;
        }
        return false;
    }
    
    void recordFailure() {
        failures.incrementAndGet();
        lastFailureTime = System.currentTimeMillis();
    }
}

熔断器有三种状态:Closed(正常放行)、Open(直接拒绝)、Half-Open(试探性放行)。当连续失败达到阈值(5次)时进入Open状态,30秒后进入Half-Open状态放行一个请求试探,成功则恢复Closed,失败则重新Open。

动态路由与灰度发布实现

动态路由允许不重启网关即可调整路由规则,是灰度发布的基础。通过Nacos/Apollo配置中心存储路由规则,网关监听配置变更动态刷新:

// 动态路由监听
@Component
public class DynamicRouteListener implements ApplicationEventPublisherAware {
    
    @Autowired
    private RouteDefinitionLocator routeDefinitionLocator;
    
    @NacosConfigListener(dataId = "gateway-routes.json")
    public void onRouteChange(String config) {
        List<RouteDefinition> routes = JSON.parseArray(config, RouteDefinition.class);
        
        // 清除旧路由
        routeDefinitionLocator.getRouteDefinitions().collectList()
            .subscribe(oldRoutes -> {
                oldRoutes.forEach(route -> 
                    publisher.publishEvent(new RefreshRoutesEvent(this))
                );
            });
        
        // 加载新路由
        routes.forEach(route ->
            publisher.publishEvent(new RefreshRoutesEvent(this))
        );
    }
    
    private ApplicationEventPublisher publisher;
    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
        this.publisher = publisher;
    }
}

灰度发布通过路由权重控制流量分配。10%流量到新版本,90%到旧版本,逐步增加新版本权重直到全量切换。结合Header标记或Cookie标记实现按用户灰度:特定用户群体先体验新功能,验证无问题后扩展到全部用户。API网关作为流量控制中枢,配合服务注册中心和配置中心,实现了微服务治理的核心闭环。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/api-wang-guan-jia-gou-she-ji-shi-zhan-xian-liu-rong-duan-yu/

(0)
小编小编
上一篇 4小时前
下一篇 4小时前

相关推荐