Sentinel 示例

完整 Sentinel 示例与解释

1. 项目结构

复制代码
sentinel-demo/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/
│   │   │       └── example/
│   │   │           ├── config/          # Sentinel 规则配置
│   │   │           │   ├── FlowRuleConfig.java
│   │   │           │   └── DegradeRuleConfig.java
│   │   │           ├── controller/      # 控制器
│   │   │           │   └── DemoController.java
│   │   │           └── Application.java # 启动类
│   │   └── resources/
│   │       └── application.yml

2. 完整代码示例

2.1 启动类 (Application.java)

java 复制代码
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

2.2 流量控制规则配置 (FlowRuleConfig.java)

java 复制代码
@Configuration
public class FlowRuleConfig implements CommandLineRunner {
    
    @Override
    public void run(String... args) {
        List<FlowRule> rules = new ArrayList<>();
        
        // 为DemoController#testFlow定义QPS限流规则
        FlowRule rule1 = new FlowRule();
        rule1.setResource("DemoController#testFlow");
        rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule1.setCount(2); // QPS阈值=2
        rules.add(rule1);
        
        // 为DemoController#testParamFlow定义参数限流规则
        FlowRule rule2 = new FlowRule();
        rule2.setResource("DemoController#testParamFlow");
        rule2.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule2.setCount(1);
        rule2.setParamIdx(0); // 对第一个参数限流
        rules.add(rule2);
        
        FlowRuleManager.loadRules(rules);
    }
}

2.3 熔断规则配置 (DegradeRuleConfig.java)

java 复制代码
@Configuration
public class DegradeRuleConfig implements CommandLineRunner {
    
    @Override
    public void run(String... args) {
        List<DegradeRule> rules = new ArrayList<>();
        
        // 为DemoController#testDegrade定义熔断规则
        DegradeRule rule = new DegradeRule();
        rule.setResource("DemoController#testDegrade");
        rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
        rule.setCount(5);    // 异常数阈值=5
        rule.setTimeWindow(10); // 熔断时间窗口=10秒
        rules.add(rule);
        
        DegradeRuleManager.loadRules(rules);
    }
}

2.4 控制器 (DemoController.java)

java 复制代码
@RestController
@RequestMapping("/demo")
public class DemoController {
    
    private static final Random random = new Random();
    
    // ========== 流量控制示例 ==========
    
    /**
     * 基础流量控制
     */
    @GetMapping("/flow")
    @SentinelResource(value = "DemoController#testFlow", 
                     blockHandler = "handleFlowBlock")
    public String testFlow() {
        return "Flow test passed";
    }
    
    /**
     * 参数限流示例
     */
    @GetMapping("/paramFlow")
    @SentinelResource(value = "DemoController#testParamFlow",
                     blockHandler = "handleParamFlowBlock")
    public String testParamFlow(@RequestParam("userId") Long userId) {
        return "Param flow test passed for user " + userId;
    }
    
    // ========== 熔断降级示例 ==========
    
    /**
     * 熔断降级测试
     */
    @GetMapping("/degrade")
    @SentinelResource(value = "DemoController#testDegrade",
                     blockHandler = "handleDegradeBlock",
                     fallback = "handleDegradeFallback")
    public String testDegrade() {
        // 模拟60%的异常率
        if (random.nextInt(10) < 6) {
            throw new RuntimeException("Random error occurred");
        }
        return "Degrade test passed";
    }
    
    // ========== 异常处理方法 ==========
    
    // 流量控制Block处理
    public String handleFlowBlock(BlockException ex) {
        return "Flow control triggered: " + ex.getClass().getSimpleName();
    }
    
    // 参数限流Block处理
    public String handleParamFlowBlock(Long userId, BlockException ex) {
        return "User " + userId + " is blocked by param flow rule";
    }
    
    // 熔断Block处理
    public String handleDegradeBlock(BlockException ex) {
        return "Circuit breaker opened: " + ex.getClass().getSimpleName();
    }
    
    // 熔断Fallback处理
    public String handleDegradeFallback(Throwable t) {
        return "Fallback for: " + t.getMessage();
    }
}

3. 详细解释

3.1 资源定义

资源通过 @SentinelResource 注解定义:

java 复制代码
@SentinelResource(
    value = "DemoController#testFlow",  // 资源名称
    blockHandler = "handleFlowBlock"   // BlockException处理方法
)

3.2 规则类型与配置

流量控制规则 (FlowRule)
java 复制代码
FlowRule rule = new FlowRule();
rule.setResource("DemoController#testFlow"); // 资源名
rule.setGrade(RuleConstant.FLOW_GRADE_QPS); // 限流类型(QPS/线程数)
rule.setCount(2);  // 阈值
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT); // 控制策略
熔断降级规则 (DegradeRule)
java 复制代码
DegradeRule rule = new DegradeRule();
rule.setResource("DemoController#testDegrade");
rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT); // 熔断策略
rule.setCount(5);    // 阈值(异常数/异常比例/RT)
rule.setTimeWindow(10); // 熔断时长(秒)

3.3 异常处理机制

BlockHandler
  • 处理 Sentinel 规则触发的 BlockException
  • 方法签名要求:
    • 返回类型与原方法相同
    • 参数列表需要包含原方法参数+BlockException
    • 必须位于同一个类中

示例:

java 复制代码
public String handleFlowBlock(BlockException ex) {
    // 处理逻辑
}
Fallback
  • 处理业务逻辑抛出的非BlockException
  • 方法签名要求:
    • 返回类型与原方法相同
    • 参数列表需要包含原方法参数+Throwable
    • 可选,不强制要求在同一类中

示例:

java 复制代码
public String handleDegradeFallback(Throwable t) {
    // 处理逻辑
}

4. 测试场景

4.1 流量控制测试

  1. 快速刷新 /demo/flow 接口
  2. 当QPS超过2时,会看到 handleFlowBlock 返回的消息

4.2 参数限流测试

  1. 用不同userId频繁请求 /demo/paramFlow?userId=xxx
  2. 对同一userId的QPS超过1时会被限流

4.3 熔断测试

  1. 连续请求 /demo/degrade 接口
  2. 当异常数达到5次后触发熔断
  3. 熔断期间请求会直接进入 handleDegradeBlock
  4. 10秒后会自动恢复

5. 最佳实践建议

  1. 资源命名规范

    • 使用 类名#方法名 格式
    • 保持全局唯一性
  2. 规则配置

    • 生产环境建议通过控制台动态配置
    • 开发环境可以使用代码初始化
  3. 异常处理

    • 区分业务异常和流控异常
    • 提供友好的降级响应
  4. 监控整合

    • 集成Sentinel控制台实时监控
    • 配置告警规则
  5. 性能考虑

    • 避免在BlockHandler/Fallback中执行耗时操作
    • 保持处理逻辑简单高效

这个完整示例展示了Sentinel的核心功能,包括资源定义、规则配置和异常处理机制,可以作为实际项目中的参考实现。