Spring Cloud Gateway路由与限流实战指南
1. 为什么需要网关路由与限流在微服务架构中API网关作为所有请求的入口承担着至关重要的流量管控职责。我经历过一个线上事故某次促销活动期间由于未配置限流策略突发流量直接击穿了订单服务导致整个系统雪崩。这正是网关路由与限流存在的核心价值路由控制将不同特征的请求精准路由到对应服务实例流量防护避免突发流量导致服务不可用资源隔离防止单一接口占用全部系统资源Spring Cloud Gateway作为Spring官方推出的第二代网关框架相比Zuul具有更好的性能基于Netty实现异步非阻塞和更丰富的功能扩展性。其核心架构如下图所示客户端请求 - Gateway Handler Mapping - Gateway Web Handler - 过滤器链 - 目标服务 ↑ 路由断言(Predicate)匹配2. 路由配置实战从基础到高阶2.1 基础路由配置在application.yml中配置最简单的路由规则spring: cloud: gateway: routes: - id: user-service uri: lb://user-service # lb表示从注册中心负载均衡 predicates: - Path/api/users/** filters: - StripPrefix1 # 去掉/api前缀这里有几个关键点需要注意lb://前缀表示启用服务发现需要配合spring-cloud-starter-loadbalancerStripPrefix过滤器用于去除请求路径前缀路由ID应保持唯一性建议采用服务名-route的命名规范2.2 动态路由方案生产环境往往需要动态调整路由配置有两种主流实现方式方案一基于Nacos配置中心Configuration public class DynamicRouteConfig { Autowired private NacosConfigManager configManager; PostConstruct public void init() { configManager.getConfigService() .addListener(gateway-routes, DEFAULT_GROUP, new Listener() { Override public void receiveConfigInfo(String configInfo) { // 解析配置并更新路由 } }); } }方案二基于Redis的事件推送Bean public RedisMessageListenerContainer container(RedisConnectionFactory factory) { RedisMessageListenerContainer container new RedisMessageListenerContainer(); container.setConnectionFactory(factory); container.addMessageListener((message, pattern) - { // 处理路由变更事件 }, new ChannelTopic(gateway-routes-update)); return container; }提示动态路由更新时需要考虑原子性问题建议采用版本号控制或CAS机制3. 限流实现深度解析3.1 Redis令牌桶限流实战Spring Cloud Gateway内置的RequestRateLimiter过滤器基于令牌桶算法实现。完整配置示例spring: redis: host: redis-host port: 6379 cloud: gateway: routes: - id: order-service uri: lb://order-service filters: - name: RequestRateLimiter args: redis-rate-limiter.replenishRate: 100 # 每秒补充令牌数 redis-rate-limiter.burstCapacity: 200 # 令牌桶容量 key-resolver: #{ipKeyResolver} # 限流维度自定义KeyResolver示例按IP限流Bean public KeyResolver ipKeyResolver() { return exchange - Mono.just( exchange.getRequest() .getRemoteAddress() .getAddress() .getHostAddress() ); }算法原理令牌桶以固定速率replenishRate生成令牌每个请求消耗1个令牌当突发流量来临时最多允许消耗burstCapacity个令牌令牌不足时返回HTTP 4293.2 Sentinel集成方案相比Redis方案Sentinel提供更丰富的流量控制能力添加依赖dependency groupIdcom.alibaba.cloud/groupId artifactIdspring-cloud-alibaba-sentinel-gateway/artifactId /dependency配置流控规则持久化到Nacosspring: cloud: sentinel: datasource: gw-flow: nacos: server-addr: nacos-host:8848 dataId: gateway-flow-rules ruleType: gw-flowNacos中的规则配置示例[ { resource: order-service, count: 50, intervalSec: 1, controlBehavior: 0, burst: 100, paramItem: { parseStrategy: 3, // 按请求IP限流 fieldName: remoteAddr } } ]Sentinel支持多种流控模式直接拒绝CONTROL_BEHAVIOR_DEFAULT匀速排队CONTROL_BEHAVIOR_RATE_LIMITER冷启动CONTROL_BEHAVIOR_WARM_UP4. 生产环境最佳实践4.1 灰度发布路由配置通过Header匹配实现灰度路由filters: - name: RequestRateLimiter args: # 限流配置... - name: Header args: header: X-Env-Tag regex: canary uri: lb://order-service-canary4.2 限流异常处理自定义限流响应体Bean Order(-1) public GlobalExceptionHandler globalExceptionHandler() { return (exchange, ex) - { if (ex instanceof RateLimiterExceededException) { exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS); return exchange.getResponse().writeWith( Mono.just(exchange.getResponse() .bufferFactory() .wrap({\code\:429,\msg\:\请求过于频繁\}.getBytes())) ); } return Mono.error(ex); }; }4.3 监控与告警建议配置以下监控指标网关请求QPS按路由分组限流触发次数平均响应时间错误率Prometheus配置示例management: endpoints: web: exposure: include: prometheus metrics: tags: application: ${spring.application.name}5. 性能调优经验在实际压测中我们发现以下配置能显著提升网关性能Netty线程池优化server: netty: max-threads: 16 # 根据CPU核心数调整 accept-threads: 2响应式编程优化Bean public WebClient webClient() { return WebClient.builder() .clientConnector(new ReactorClientHttpConnector( HttpClient.create() .compress(true) .keepAlive(true) .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000) )) .build(); }Redis连接池配置spring: redis: lettuce: pool: max-active: 32 max-idle: 16 min-idle: 8经过这些优化后在8核16G的机器上网关的吞吐量从原来的5k QPS提升到了15k QPS。