服务流控(Sentinel)

2024-02-17 09:25:37 浏览数 (1)

引入依赖

代码语言:javascript复制
<!-- 必须的 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- sentinel 核心库 -->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-core</artifactId>
    <version>1.8.0</version>
</dependency>

实现流控

编码实现

  • 限流实现
代码语言:javascript复制
    private static final Logger logger = LoggerFactory.getLogger(HelloController.class);
    private static final String RESOURCE_NAME = "hello";

    @RequestMapping("/hello")
    public String hello() {
        Entry entry = null;
        // 务必保证finally会被执行
        try {
            // 资源名可使用任意有业务语义的字符串
            entry = SphU.entry(RESOURCE_NAME);
            // 被保护的业务逻辑
            // do something...
            String str = "hello world";
            logger.info("            "   str);
            return str;
        } catch (BlockException e1) {
            // 资源访问阻止,被限流或被降级
            // 进行相应的处理操作
            logger.info("block!!!!!");
            return "被流控了!!!!";
        } catch (Exception e) {
            // 若需要配置降级规则。则需要通过这种方式记录业务异常
            Tracer.traceEntry(e, entry);
        } finally {
            if (entry != null) {
                entry.exit();
            }
        }
        return null;
    }
  • 注册流控规则
代码语言:javascript复制
    @PostConstruct
    private static void initFlowControlRules() { // 通常设置在服务提供方
        // 流控规则列表
        List<FlowRule> flowRuleList = new ArrayList<>();

        // 流控规则
        FlowRule helloFlowRule = new FlowRule();
        // 设置流控的资源名称
        helloFlowRule.setResource(RESOURCE_NAME);
        // 设置流控规则 QPS
        helloFlowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        // 设置流控的阈值
        // Set limit QPS to 20
        helloFlowRule.setCount(1);

        flowRuleList.add(helloFlowRule);
        
        FlowRuleManager.loadRules(flowRuleList);
   }
  • 效果呈现

注解实现

  • 引入依赖
代码语言:javascript复制
<!--  @SentinelResource  -->
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-annotation-aspectj</artifactId>
    <version>1.8.0</version>
</dependency>
  • 增加切面
    • 启动类
代码语言:javascript复制
    @Bean
    public SentinelResourceAspect sentinelResourceAspect() {
        return new SentinelResourceAspect();
    }
    • 配置类
代码语言:javascript复制
/**
 * 1. 使用注解@SentinelResource
 * 2. 使用了 Spring AOP
 * 3. 通过配置的方式将 SentinelResourceAspect 注册为一个 Spring Bean
 */
@Configuration
public class AopConfiguration {

    @Bean
    public SentinelResourceAspect sentinelResourceAspect() {
        return new SentinelResourceAspect();
    }
}
  • 注解使用
代码语言:javascript复制
    /**
     * 使用注解 使用Sentinel
     *
     * @SentinelResource: 依赖:
     * <dependency>
     *      <groupId>com.alibaba.csp</groupId>
     *      <artifactId>sentinel-annotation-aspectj</artifactId>
     *      <version>1.8.0</version>
     * </dependency>
     * 1. value: 资源名称
     * 2. blockHandler 流控降低处理器 (默认和接口实现方法在同一个类中)
     * 3. blockHandlerClass 指定处理器类
     * 4. fallback  业务异常处理
     * 5. fallbackClass 指定异常处理器类
     * 6. blockHandler 和 fallback 同时配置, blockHandler 优先级高
     * 7. exceptionsToIgnore 排除不需要处理的异常 -> exceptionsToIgnore = {}
     */
    @RequestMapping("/user")
    @SentinelResource(value = USER_RESOURCE_NAME, blockHandler = "blockHandlerForGetUser",
//            fallback = "fallBackForGetUser",
            exceptionsToIgnore = {})
    public User getUser(String id) {
        // int i = 1 / 0;
        return new User(id, "Quentin");
    }

    /**
     * 注意:
     * 1. 必须是public, 若放在其他类中 blockHandlerClass 则必须为 public static
     * 2. 返回值 需和原接口方法的返回值保持一致 且 参数包含原方法的参数
     * 3. 额外增加  异常参数 BlockException
     *
     * @param id
     * @param be
     * @return
     */
    public User blockHandlerForGetUser(String id, BlockException be) {
        logger.info("        注解流控");
        return new User(id, "被流控了!!!");
    }
  • 增加流控规则
代码语言:javascript复制
    @PostConstruct
    private static void initFlowControlRules() { // 通常设置在服务提供方
        // 流控规则列表
        List<FlowRule> flowRuleList = new ArrayList<>();


        // 流控规则
        FlowRule userFlowRule = new FlowRule();
        // 设置流控的资源名称
        userFlowRule.setResource(USER_RESOURCE_NAME);
        // 设置流控规则 QPS
        userFlowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        // 设置流控的阈值
        // Set limit QPS to 20
        userFlowRule.setCount(1);

        flowRuleList.add(userFlowRule);

        FlowRuleManager.loadRules(flowRuleList);
    }
  • 效果

0 人点赞