简介

我们说的资源,可以是任何东西,服务,服务里的方法,甚至是一段代码。使用 Sentinel 来进行资源保护,主要分为两个步骤:

  • 定义资源
  • 定义规则

先把可能需要保护的资源定义好,之后再配置规则。也可以理解为,只要有了资源,我们就可以在任何时候灵活地定义各种流量控制规则。在编码的时候,只需要考虑这个代码是否需要保护,如果需要保护,就将之定义为一个资源。

对于主流的框架,我们提供适配,只需要按照适配中的说明配置,Sentinel 就会默认定义提供的服务,方法等为资源。

定义资源

抛出异常的方式定义资源

用这种方式,当资源发生了限流之后会抛出 BlockException。这个时候可以捕捉异常,进行限流之后的逻辑处理。示例代码如下:

  1. Entry entry = null;
  2. // 务必保证finally会被执行
  3. try {
  4. // 资源名可使用任意有业务语义的字符串
  5. entry = SphU.entry("自定义资源名");
  6. /**
  7. * 被保护的业务逻辑
  8. */
  9. } catch (BlockException e1) {
  10. // 资源访问阻止,被限流或被降级
  11. // 进行相应的处理操作
  12. } finally {
  13. if (entry != null) {
  14. entry.exit();
  15. }
  16. }

返回布尔值方式定义资源

用这种方式,当资源发生了限流之后会返回 false,这个时候可以根据返回值,进行限流之后的逻辑处理。示例代码如下:

  1. // 资源名可使用任意有业务语义的字符串
  2. if (SphO.entry("自定义资源名")) {
  3. // 务必保证finally会被执行
  4. try {
  5. /**
  6. * 被保护的业务逻辑
  7. */
  8. } finally {
  9. SphO.exit();
  10. }
  11. } else {
  12. // 资源访问阻止,被限流或被降级
  13. // 进行相应的处理操作
  14. }

判断限流降级异常

通过以下方法判断:

  1. BlockException.isBlockException(Throwable t);

主流框架的适配

为了减少开发的复杂程度,我们对大部分的主流框架,例如 Dubbo, RocketMQ, Spring Cloud 等都做了适配。您只需要引入对应的依赖,它们的方法,服务,都会进行默认的埋点。

参见: 主流框架的适配

定义规则

Sentinel 的所有规则都可以在内存态中动态地查询及修改,修改之后立即生效。同时 Sentinel 也提供相关 API,供您来定制自己的规则策略。

规则的定义

Sentinel 支持三种规则:流量控制规则熔断降级规则以及系统保护规则

流量控制规则 (FlowRule)

流量规则的定义

重要属性:

Field 说明 默认值
resource 资源名,资源名是限流规则的作用对象
count 限流阈值
grade 限流阈值类型,是按照 QPS 还是线程数 默认根据 QPS
limitApp 是否根据调用者来限流
strategy 判断的根据是资源自身,还是根据其它资源 (refResource),还是根据链路入口 (refResource) 根据资源本身
controlBehavior 发生拦截后是直接拒绝,还是排队等待,还是慢启动模式 直接拒绝

同一个资源可以同时有多个限流规则。

通过代码定义流量控制规则

理解上面规则的定义之后,我们可以通过调用 FlowRuleManager.loadRules() 方法来用硬编码的方式定义流量控制规则,比如:

  1. private static void initFlowQpsRule() {
  2. List<FlowRule> rules = new ArrayList<>();
  3. FlowRule rule1 = new FlowRule();
  4. rule1.setResource(KEY);
  5. // set limit qps to 20
  6. rule1.setCount(20);
  7. rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
  8. rule1.setLimitApp("default");
  9. rules.add(rule1);
  10. FlowRuleManager.loadRules(rules);
  11. }

更多详细内容可以参考 流量控制

熔断降级规则 (DegradeRule)

熔断降级规则包含下面几个重要的属性:

Field 说明 默认值
resource 资源名,资源名是限流规则的作用对象
count 限流阈值
grade 根据 RT 降级还是根据异常比例降级 RT
timeWindow 降级的时间

同一个资源可以同时有多个降级规则。

理解上面规则的定义之后,我们可以通过调用 DegradeRuleManager.loadRules() 方法来用硬编码的方式定义流量控制规则。

  1. private static void initDegradeRule() {
  2. List<DegradeRule> rules = new ArrayList<>();
  3. DegradeRule rule = new DegradeRule();
  4. rule.setResource(KEY);
  5. // set threshold rt, 10 ms
  6. rule.setCount(10);
  7. rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
  8. rule.setTimeWindow(10);
  9. rules.add(rule);
  10. DegradeRuleManager.loadRules(rules);
  11. }

更多详情可以参考 熔断降级

系统保护规则 (SystemRule)

规则包含下面几个重要的属性:

Field 说明 默认值
highestSystemLoad 最大的 load1 -1 (不生效)
avgRt 所有入口流量的平均响应时间 -1 (不生效)
maxThread 入口流量的最大并发数 -1 (不生效)

理解上面规则的定义之后,我们可以通过调用 SystemRuleManager.loadRules() 方法来用硬编码的方式定义流量控制规则。

  1. private static void initDegradeRule() {
  2. List<SystemRule> rules = new ArrayList<>();
  3. SystemRule rule = new SystemRule();
  4. rule.setHighestSystemLoad(10);
  5. rules.add(rule);
  6. DegradeRuleManager.loadRules(rules);
  7. }

更多详情可以参考 系统负载保护

查询更改规则

运行下面命令,则会返回现有生效的规则:

  1. curl http://localhost:8719/getRules?type=<XXXX>

其中,type=flow 以 JSON 格式返回现有的限流规则;degrade 则返回现有生效的降级规则列表;system 则返回系统保护规则。

同时也可以通过下面命令来修改已有规则:

  1. curl http://localhost:8719/setRules?type=<XXXX>&data=<DATA>

其中,type 可以输入 flowdegrade 等方式来制定更改的规则种类,data 则是对应的 JSON 格式的规则。

定制自己的持久化规则

上面的规则配置,都是存在内存中的。即如果应用重启,这个规则就会失效。因此我们提供了开放的接口,您可以通过实现 DataSource 接口的方式,来自定义规则的存储数据源。通常我们的建议有:

  • 整合动态配置系统,如 etcd、Nacos,动态地实时刷新配置规则
  • 结合 DB、VCS 等来实现该规则
  • 配合 Sentinel Dashboard 使用
    更多详情请参考动态规则配置

规则生效的效果

除了在业务代码逻辑上看到规则生效,我们也可以通过下面简单的方法,来校验规则生效的效果:

原文: https://github.com/alibaba/Sentinel/wiki/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8