Spring Cloud Gateway限流熔断配置:Sentinel集成与规则持久化方案

微服务架构下,API网关承担流量入口职责,限流熔断是保障系统高可用设计的核心机制。Spring Cloud Gateway作为Spring生态推荐的网关组件,集成Sentinel可实现路由级限流、服务熔断降级和规则动态推送。本文从集成配置到规则持久化,给出生产环境落地的完整方案。

Spring Cloud Gateway集成Sentinel基础配置

Spring Cloud Gateway 4.x与Sentinel 1.8.x的集成通过spring-cloud-starter-alibaba-sentinel-gateway模块完成。Sentinel为Gateway提供自定义SlotChain,在路由转发前执行限流判断。

<!-- pom.xml 依赖配置 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
    <version>4.1.4</version>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel-gateway</artifactId>
    <version>2023.0.1.2</version>
</dependency>
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
    <version>1.8.8</version>
</dependency>
# application.yml
server:
  port: 8080

spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/api/users/**
          filters:
            - StripPrefix=1
            - name: RequestSize
              args:
                maxSize: 10MB
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/api/orders/**
          filters:
            - StripPrefix=1
            - name: Retry
              args:
                retries: 3
                statuses: BAD_GATEWAY,GATEWAY_TIMEOUT
                backoff:
                  firstBackoff: 100ms
                  maxBackoff: 500ms
                  factor: 2
    sentinel:
      transport:
        dashboard: 127.0.0.1:8858
        port: 8719
      eager: true  # 网关启动即初始化Sentinel
      filter:
        enabled: false  # 关闭默认WebFilter,使用Gateway专用Slot

eager=true确保网关启动时立即与Sentinel Dashboard建立连接,避免首批请求未被监控。filter.enabled=false关闭Sentinel默认的Web MVC过滤器,因为Gateway基于Reactor而非Servlet,需要使用Gateway专用的限流入口。

路由级限流规则配置与自定义异常响应

Sentinel Gateway适配器自动将每个路由ID注册为资源。限流规则可直接针对路由ID配置,也可通过自定义API分组聚合多个路由。QPS超限后默认返回429状态码,生产环境需要自定义错误响应体。

@Configuration
public class GatewayConfig {
    
    @PostConstruct
    public void init() {
        // 自定义限流异常处理器
        GatewayCallbackManager.setBlockHandler((exchange, ex) -> {
            Map<String, Object> result = new HashMap<>();
            result.put("code", 429);
            result.put("message", "请求过于频繁,请稍后重试");
            result.put("timestamp", System.currentTimeMillis());
            result.put("path", exchange.getRequest().getPath().value());
            
            return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS)
                .contentType(MediaType.APPLICATION_JSON)
                .body(BodyInserters.fromValue(result));
        });
        
        // 自定义API分组(跨路由限流)
        Set<ApiDefinition> definitions = new HashSet<>();
        ApiDefinition api = new ApiDefinition("payment-api")
            .setPredicateItems(Collections.singleton(
                new ApiPathPredicateItem()
                    .setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX)
                    .setPattern("/api/payment/")
            ));
        definitions.add(api);
        GatewayApiDefinitionManager.loadApiDefinitions(definitions);
    }
}
// 动态添加限流规则
public class FlowRuleManager {
    
    public static void addRouteFlowRule(String routeId, int count) {
        Set<FlowRule> rules = new HashSet<>();
        FlowRule rule = new FlowRule(routeId);
        rule.setResourceMode(SentinelGatewayConstants.RESOURCE_MODE_ROUTE_ID);
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule.setCount(count);  // QPS阈值
        rule.setLimitApp("default");
        rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT);
        rules.add(rule);
        GatewayFlowRuleManager.loadRules(rules);
    }
    
    public static void addParamFlowRule(String routeId, String paramName, int count) {
        // 基于请求参数限流(如按userId限流)
        GatewayParamFlowRule rule = new GatewayParamFlowRule(routeId)
            .setParamIdx(0)  // 参数索引
            .setCount(count)
            .setGrade(RuleConstant.FLOW_GRADE_QPS);
        
        // 从请求头提取参数
        rule.setParamItem(
            new GatewayParamFlowRule.ParamItem()
                .setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_HEADER)
                .setFieldName("X-User-Id")
        );
        
        Set<GatewayParamFlowRule> rules = new HashSet<>();
        rules.add(rule);
        GatewayParamFlowRuleManager.loadRules(rules);
    }
}

服务熔断降级规则与慢调用比例策略

限流保护网关自身,熔断保护下游服务。Sentinel支持RT(响应时间)和异常比例两种熔断策略。慢调用比例策略在指定窗口内慢调用占比超过阈值时触发熔断,适合对延迟敏感的场景。

public class DegradeRuleConfig {
    
    public static void initDegradeRules() {
        List<DegradeRule> rules = new ArrayList<>();
        
        // 慢调用比例熔断
        DegradeRule slowCallRule = new DegradeRule("order-service")
            .setGrade(CircuitBreakerStrategy.SLOW_REQUEST_RATIO.getType())
            .setCount(500)          // 慢调用阈值:500ms
            .setSlowRatioThreshold(0.6)  // 慢调用比例阈值:60%
            .setMinRequestAmount(5)      // 最小请求数
            .setStatIntervalMs(10000)    // 统计窗口:10秒
            .setTimeWindow(10);          // 熔断持续时间:10秒
        rules.add(slowCallRule);
        
        // 异常比例熔断
        DegradeRule exceptionRule = new DegradeRule("order-service")
            .setGrade(CircuitBreakerStrategy.ERROR_RATIO.getType())
            .setCount(0.5)          // 异常比例阈值:50%
            .setMinRequestAmount(10)
            .setStatIntervalMs(10000)
            .setTimeWindow(15);
        rules.add(exceptionRule);
        
        // 异常数熔断
        DegradeRule exceptionCountRule = new DegradeRule("payment-service")
            .setGrade(CircuitBreakerStrategy.ERROR_COUNT.getType())
            .setCount(20)           // 异常数阈值:20
            .setMinRequestAmount(20)
            .setStatIntervalMs(60000)
            .setTimeWindow(30);
        rules.add(exceptionCountRule);
        
        DegradeRuleManager.loadRules(rules);
    }
}

熔断触发后的降级处理通过Gateway的fallback机制实现。被熔断的服务请求返回预设的降级响应,而非直接报错。

@Configuration
public class FallbackConfig {
    
    @Bean
    public RouterFunction<ServerResponse> fallbackRouter() {
        return RouterFunctions.route()
            .GET("/fallback/order", request -> 
                ServerResponse.ok()
                    .contentType(MediaType.APPLICATION_JSON)
                    .body(BodyInserters.fromValue(Map.of(
                        "code", 503,
                        "message", "订单服务暂时不可用,请稍后重试",
                        "fallback", true
                    )))
            )
            .GET("/fallback/payment", request ->
                ServerResponse.ok()
                    .contentType(MediaType.APPLICATION_JSON)
                    .body(BodyInserters.fromValue(Map.of(
                        "code", 503,
                        "message", "支付服务降级中,请稍后重试",
                        "fallback", true
                    )))
            )
            .build();
    }
}

// 路由配置中指定fallback URI
// application.yml
/*
spring:
  cloud:
    gateway:
      routes:
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/api/orders/**
          filters:
            - name: CircuitBreaker
              args:
                name: orderCircuitBreaker
                fallbackUri: forward:/fallback/order
*/

规则持久化方案:Nacos动态配置中心

Sentinel默认将规则存储在内存中,应用重启后规则丢失。生产环境必须将规则持久化到配置中心,Nacos是Spring Cloud Alibaba生态的推荐方案。规则变更通过Nacos配置监听实时推送到网关节点。

# application.yml Sentinel Nacos数据源配置
spring:
  cloud:
    sentinel:
      datasource:
        # 限流规则
        flow:
          nacos:
            server-addr: ${NACOS_ADDR:127.0.0.1:8848}
            namespace: ${NACOS_NAMESPACE:sentinel}
            group-id: SENTINEL_GROUP
            data-id: ${spring.application.name}-flow-rules.json
            rule-type: flow
        # 熔断规则
        degrade:
          nacos:
            server-addr: ${NACOS_ADDR:127.0.0.1:8848}
            namespace: ${NACOS_NAMESPACE:sentinel}
            group-id: SENTINEL_GROUP
            data-id: ${spring.application.name}-degrade-rules.json
            rule-type: degrade
        # 网关限流规则
        gateway-flow:
          nacos:
            server-addr: ${NACOS_ADDR:127.0.0.1:8848}
            namespace: ${NACOS_NAMESPACE:sentinel}
            group-id: SENTINEL_GROUP
            data-id: ${spring.application.name}-gateway-flow-rules.json
            rule-type: gw-flow

Nacos中存储的限流规则JSON格式示例:

[
  {
    "resource": "user-service",
    "resourceMode": 0,
    "grade": 1,
    "count": 500,
    "intervalSec": 1,
    "burst": 100,
    "controlBehavior": 0,
    "paramItem": null
  },
  {
    "resource": "order-service",
    "resourceMode": 0,
    "grade": 1,
    "count": 300,
    "intervalSec": 1,
    "burst": 50,
    "controlBehavior": 2,
    "maxQueueingTimeoutMs": 500,
    "paramItem": null
  }
]

controlBehavior=2表示匀速排队模式,请求在阈值内匀速通过,超出部分排队等待,适合突发流量削峰场景。maxQueueingTimeoutMs设置排队超时时间,超时请求被拒绝。

网关高可用部署与监控告警

网关作为流量入口自身也需要高可用保障。多实例部署配合负载均衡,通过Spring Boot Actuator暴露健康检查接口。Sentinel Dashboard提供实时监控面板,但生产环境建议接入Prometheus + Grafana做长期指标存储和告警。

# 暴露Sentinel指标到Prometheus
management:
  endpoints:
    web:
      exposure:
        include: health,info,prometheus,sentinel
  metrics:
    tags:
      application: ${spring.application.name}

# Sentinel指标自定义
@Component
public class SentinelMetricsConfig {
    
    @EventListener
    public void onBlockEvent(BlockEvent event) {
        Metrics.counter("sentinel.block.total",
            "resource", event.getResourceName(),
            "rule", event.getLimitApp(),
            "type", event.getBlockType().name()
        ).increment();
    }
    
    @EventListener
    public void onCircuitBreakerEvent(CircuitBreakerEvent event) {
        Metrics.gauge("sentinel.circuit.state",
            Tags.of("resource", event.getResourceName()),
            event.getState().ordinal()
        );
    }
}

Grafana面板建议配置以下告警规则:网关5xx错误率超过1%、单路由QPS接近限流阈值80%、熔断器处于Open状态持续超过30秒。告警通过webhook推送到运维群,触发自动化扩容或限流阈值调整流程。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/springcloudgateway-xian-liu-rong-duan-pei-zhi-sentinel-ji/

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

相关推荐