Sentinel实践-熔断和限流

文章目录

    • sentinel简介
    • 一些基本概念
      • 资源
      • 规则
      • 资源和规则的关系
    • springboot项目应用简单实践
      • pom依赖
      • AopConfiguration
      • ResourceNameDef
      • RuleDefinetion
      • 对接口限流
    • 查看效果
    • 总结

sentinel简介

Sentinel 是面向分布式服务架构的高可用流量防护组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。

Sentinel 具有以下特性:

  • 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
  • 完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
  • 广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。
  • 完善的 SPI 扩展点:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。

一些基本概念

资源

所有的监控、限流、熔断等等操作,都是基于“资源”做的。

资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。在接下来的文档中,我们都会用资源来描述代码块。

只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。

资源在我看来即一个应用内唯一的字符串。

规则

围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。

资源和规则的关系

资源和规则是多对多的关系,一个资源可以配置多个规则,一个规则也可以在多个资源内使用。

当一个资源有多个规则时,多条规则存在与关系,即逐一进行检查,全部通过才算通过。(责任链模式)

springboot项目应用简单实践

由于我们项目中已有监控平台,所以仅仅使用sentinel做一个针对某几个接口的熔断限流的操作
如果要做到全平台监控,建议使用sentinel官方推荐的集成方案,那种方案会对所有url都创建一个资源。
项目环境:springboot

主要有三个类:

  • AopConfiguration:切面配置。sentinel可以用注解+切面的形式实施对资源的管理
  • ResourceNameDef:资源定义
  • RuleDefination:规则定义

pom依赖

<dependency>
    <groupId>com.alibaba.cspgroupId>
    <artifactId>sentinel-coreartifactId>
    <version>1.7.2version>
dependency>

<dependency>
    <groupId>com.alibaba.cspgroupId>
    <artifactId>sentinel-annotation-aspectjartifactId>
    <version>1.7.2version>
dependency>

AopConfiguration

/**
 * @author Eric Zhao
 */
@Configuration
public class AopConfiguration {
    private static final Logger log = LogUtil.getLogger(AopConfiguration.class);

    @Bean
    public SentinelResourceAspect sentinelResourceAspect() {
        log.info("sentinelResourceAspect 装载成功");
        return new SentinelResourceAspect();
    }
}

ResourceNameDef

/**
 * @author xs
 * create time: 2020/7/24 14:48
 */
public class ResourceNameDef {
    public static final String TEST_GET= "xs.test.get";
}

RuleDefinetion

/**
 * @author xs
 * create time: 2020/7/24 14:35
 */
@Component
public class RuleDefination {
    private static final Logger log = LogUtil.getLogger(RuleDefination.class);
    @PostConstruct
    public void loadRules() {
        initFlowRule(); // 限流策略初始化
        initDegradeRule(); // 熔断策略初始化
        log.info("sentinel 规则定义完毕!");
    }

    private void initDegradeRule() {
        List<DegradeRule> rules = new ArrayList<DegradeRule>();
        DegradeRule rule = new DegradeRule();
        rule.setResource(ResourceNameDef.TEST_GET);
        // 异常率超过0.1,就认为服务不可用,执行熔断操作
        rule.setCount(0.1);
        rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO);
        rule.setTimeWindow(10);
        rule.setMinRequestAmount(20);
        rules.add(rule);
        DegradeRuleManager.loadRules(rules);
        log.info("sentinel 熔断规则定义完毕!");
    }

    private void initFlowRule() {
        List<FlowRule> rules = new ArrayList<FlowRule>();
        FlowRule rule = new FlowRule();
        rule.setResource(ResourceNameDef.TEST_GET);
        // qps上限为1:
        rule.setCount(1);
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule.setLimitApp("default");
        rules.add(rule);
        FlowRuleManager.loadRules(rules);
        log.info("sentinel 限流规则定义完毕!");
    }
}

对接口限流

定义好资源和规则之后,就可以在项目里使用了。

@RequestMapping("/test")
@RestController
public class TestCtr {

    private static final Logger log = LogUtil.getLogger(TestCtr.class);


    @SentinelResource(value = ResourceNameDef.TEST_GET,
            fallback = "getFallback")
    @RequestMapping("/get")
    public ResultInfo<Integer> get() {
        return ResultInfo.buildSucc(1);
    }
    
    public ResultInfo<Integer> getFallback(Throwable t) {
        log.info("请求限制了:e={}, msg={}", t.getClass().getName(), t.getMessage());
        return ResultInfo.buildFail();
    }

}

查看效果

上面的规则定义qps=1,即每秒只能进来一个请求。所以快速请求两次/test/get结果如下:

第一次:

{
  "code": 1,
  "message": "success"
}

第二次

{
  "code": -1,
  "message": "fail"
}

此时查看日志会有

2020-07-24 16:47:57.517 [http-nio-8889-exec-4] INFO  xs.test.TestCtr - 请求限制了:e=com.alibaba.csp.sentinel.slots.block.flow.FlowException, msg=null

架子初步搭建完毕,可以看到限流时异常为FlowException,可以推断出不同的策略限制,会抛出不同的异常,可以针对处理。

总结

  1. sentinel源码中有许多demo,使用起来照抄很方便
  2. 下一步计划是学习限流、熔断策略有哪些。

你可能感兴趣的:(JAVA学习笔记)