微服务实战 03 Sentinel 机制和工作原理解析


参考《Spring Cloud Alibaba 微服务原理与实战》
上一篇介绍了 Sentinel 的作用 以及 限流、熔断、降级的理解

微服务实战 02 Sentinel 入门
这一节接着上一文了解一下 Sentinel 的使用

Sentinel 定义资源的几种方式

抛出异常式定义资源

注意: SphU.entry(xxx) 需要与 entry.exit() 方法成对出现,匹配调用,否则会导致调用链记录异常,抛出 ErrorEntryFreeException 异常。 1.5.0 版本开始可以利用 try-with-resources 特性

// 1.5.0 版本开始可以利用 try-with-resources 特性
// 资源名可使用任意有业务语义的字符串,比如方法名、接口名或其它可唯一标识的字符串。
try (Entry entry = SphU.entry("resourceName")) {
  // 被保护的业务逻辑
  // do something here...
} catch (BlockException ex) {
  // 资源访问阻止,被限流或被降级
  // 在此处进行相应的处理操作
}

返回布尔值方式定义资源

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

注解方式定义资源

// 原本的业务方法.
@SentinelResource(blockHandler = "blockHandlerForGetUser")
public User getUserById(String id) {
    throw new RuntimeException("getUserById command failed");
}

// blockHandler 函数,原方法调用被限流/降级/系统保护的时候调用
public User blockHandlerForGetUser(String id, BlockException ex) {
    return new User("admin");
}

异步调用支持

SphU.asyncEntry(xxx) 不会影响当前(调用线程)的 Context,因此以下两个 entry 在调用链上是平级关系(处于同一层),而不是嵌套关系:

try {
    AsyncEntry entry = SphU.asyncEntry(resourceName);
    // 异步调用.     // 异步回调
    doAsync(userId, result -> {
        try {
            // 在此处处理异步调用的结果.
        } finally {
            // 在回调结束后 exit.
            entry.exit();
        }
    });
} catch (BlockException ex) {
    // Request blocked.
    // Handle the exception (e.g. retry or fallback).
}

若在异步回调中需要嵌套其它的资源调用(无论是 entry 还是 asyncEntry),只需要借助 Sentinel 提供的上下文切换功能,在对应的地方通过 ContextUtil.runOnContext(context, f) 进行 Context 变换,将对应资源调用处的 Context 切换为生成的异步 Context,即可维持正确的调用链路关系。

public void handleResult(String result) {
    Entry entry = null;
    try {
        entry = SphU.entry("handleResultForAsync");
        // Handle your result here.
    } catch (BlockException ex) {
        // Blocked for the result handler.
    } finally {
        if (entry != null) {
            entry.exit();
        }
    }
}

public void someAsync() {
    try {
        AsyncEntry entry = SphU.asyncEntry(resourceName);

        // Asynchronous invocation.
        doAsync(userId, result -> {
            // 在异步回调中进行上下文变换,通过 AsyncEntry 的 getAsyncContext 方法获取异步 Context
            ContextUtil.runOnContext(entry.getAsyncContext(), () -> {
                try {
                    // 此处嵌套正常的资源调用.
                    handleResult(result);
                } finally {
                    entry.exit();
                }
            });
        });
    } catch (BlockException ex) {
        // Request blocked.
        // Handle the exception (e.g. retry or fallback).
    }
}

Sentinel 资源保护规则

  • 流量控制规则
  • 熔断降级规则
  • 系统保护规则
  • 来源访问控制规则
  • 热点参数规则

流量控制规则

在控制台可以看到这样多的配置型项
在这里插入图片描述
以上的配置对应编程式的 FlowRule 类
可以采用硬编码定义流量控制规则

    List<FlowRule> rules = new ArrayList<>();
    FlowRule rule1 = new FlowRule();
    rule1.setResource(resource);  //设置资源
    // Set max qps to 20
    rule1.setCount(20); // 设置最大 QPS
    rule1.setGrade(RuleConstant.FLOW_GRADE_QPS); //限流阈值类型,QPS 或线程数模式
    rule1.setLimitApp("default"); // 代表不区分调用来源
    rules.add(rule1);
    FlowRuleManager.loadRules(rules); // 加载规则
}

重要属性说明

Field说明默认值
resource资源名:限流规则的作用对象
count限流阈值
grade限流阈值类型,QPS 或线程数模式QPS 模式
limitApp流控针对的调用来源default,代表不区分调用来源
strategy调用关系限流策略:直接、链路、关联根据资源本身(直接)
controlBehavior流控效果(直接拒绝 / 排队等待 / 慢启动模式),不支持按调用关系限流直接拒绝

grade 限流阈值类型详解

  • 基于并发线程数
    并发线程数限流用来保护业务线程不被耗尽,如果 A 服务 调用 B 服务 , 而 B 因为一些原因导致响应延迟,对于A 服务来说,他的吞吐量会下降,也意味着占用更多的线程,极端情况下会造成线程池耗尽
    Sentinel 并发线程数限流就是统计当前请求上下文线程数量,如果超过阈值,新的请求就会被拒绝
  • QPS 每秒的查询数
    QPS 代表每秒的查询数,当QPS 达到限流的阈值时,就会触发限流策略。

controlBehavior 流量控制行为

  • 直接拒绝
    是默认的流量控制方式,载流量超出阈值时,直接抛出一个FlowExecption
  • Warm up , 冷启动(预热)
    Warm up 是冷启动(预热)方式,当流量突然增大,也可能瞬间把系统压。Warm up可以让请求处理的数量逐步自增,并在一个预期时间之后达到允许处理请求的最大值
  • 匀速排队
    匀速排队方式会严格控制请求通过的间隔时间,也就是让请求以均匀的速度通过,其实相当于上一篇文章中说过的漏桶限流
  • 冷启动+匀速排队

strategy 调用关系限流策略

调用关系爆破含调用房和被调用方,一个方法有可能会调用其他方法,形成一个调用链。所谓的调用关系流量策略,解释根据不同维度来触发流量控制

  • 直接
    调用方限流 ,根据请求来源进行流量控制
    limitApp
    * default : 不区分调用方
    * {some_origin_name}: 设置特定的调用者,只有来自这个调用者的请求才会进行流量统计和控制
    * other:表示针对除{some_origin_name}外的其他调用者进行流量控制
    由于同一个资源可以配置多条规则 {some_origin_name} -> other -> default
  • 链路
    一个被限流保护的方法,可能来自不同的调用链路. 那么Sentinel 允许真根某一个入口来进行流量统计
  • 关联
    当两个资源之间存在依赖关系或者资源争抢是,我们就说这两个资源存在关联。这个两个存在依赖关系的资源在执行时可能会因为某一个资源执行操作过于频繁而影响到另一个资源的执行效率,所以关联流量控制就是限定其中一个资源的执行流量

关联 和 链路 的区别
关联: 统计于当前资源相关的另一个资源,触发阈值时,对当前资源限流 也就是 当关联的资源达到阀值,就限流自己。
链路:统计从指定链路访问到本资源的请求,触发阈值时,对指定资源限流 也就是 当入口的资源达到阀值,就限流整个链路

熔断降级规则

在这里插入图片描述

熔断降级规则 对应DegradeRule类
重要属性说明

Field说明默认值
resource资源名,即规则的作用对象
count慢调用比例模式下为慢调用临界 RT(超出该值计为慢调用);异常比例/异常数模式下为对应的阈值[0.0,1.0]
grade熔断策略,支持慢调用比例/异常比例/异常数策略慢调用比例
timeWindow熔断时长,单位为 s
minRequestAmount熔断触发的最小请求数,请求数小于该值时即使异常比率超出阈值也不会熔断5
statIntervalMs统计时长(单位为 ms),如 60*1000 代表分钟级1000 ms
slowRatioThreshold慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入)

grade

Sentinel 提供了三种 熔断策略

  • 慢调用比例 (平均响应时间) : 如果 1 s 内持续进入5个请求,对应的平均响应时间超过了阈值,那么在接下来的时间窗口内对这个方法的调用都会自动熔断
  • 异常比例:如果每秒资源数 > minRequestAmount 并且每秒的异常总数中总通过量的比例超过阈值 count,则资源将进入降级状态。在接下来的 timeWindow 内对这个方法的调用会自动熔断
  • 异常数:当资源最近一分钟的异常数目超过阈值之后,会触发熔断,如果 timeWindow 小于 60s,则继续熔断状态后仍然可能再进入熔断状态

熔断 和 限流最终结果都是让资源降级限制访问 , 熔断是以资源为判断条件,防止因资源发生异常导致调用者请求堆积或者异常,限流以调用者为条件,防止资源被过度调用导致资源的崩溃情况

系统保护规则 (SystemRule)

在这里插入图片描述

Sentinel 系统自适应限流从整体维度对应用入口流量进行控制,结合应用的 Load、CPU 使用率、总体平均 RT、入口 QPS 和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。

对应 SystemRule 类

Field说明默认值
highestSystemLoadload1 触发值,用于触发自适应控制阶段-1 (不生效)
avgRt所有入口流量的平均响应时间-1 (不生效)
maxThread入口流量的最大并发数-1 (不生效)
qps所有入口资源的 QPS-1 (不生效)
highestCpuUsage当前系统的 CPU 使用率(0.0-1.0)-1 (不生效)

访问控制规则 (AuthorityRule)

在这里插入图片描述

很多时候,我们需要根据调用方来限制资源是否通过,这时候可以使用 Sentinel 的访问控制(黑白名单)的功能。黑白名单根据资源的请求来源(origin)限制资源是否通过,若配置白名单则只有请求来源位于白名单内时才可通过;若配置黑名单则请求来源位于黑名单时不通过,其余的请求通过。

授权规则,即黑白名单规则(AuthorityRule)非常简单,主要有以下配置项:

  • resource:资源名,即限流规则的作用对象
  • limitApp:对应的黑名单/白名单,不同 origin 用 , 分隔,如 appA,appB
  • strategy:限制模式,AUTHORITY_WHITE 为白名单模式,AUTHORITY_BLACK 为黑名单模式,默认为白名单模式

热点规则 (ParamFlowRule)

热点限流在以下场景使用较多

  • 服务层网关:防止网络爬虫和恶意攻击,一种常用方法就是限制爬虫的IP地址,客户端IP地址就是一种热点参数
  • 写数据的服务:例如数据写入数据库之类的服务,如果时同一条数据的写入会出现抢占所的情况,导致大量超时和失败,出现这个中情况一般又两种解决方案: 修改存储设计、对热点参数限流
    在这里插入图片描述
    热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效

在这里插入图片描述

Sentinel的工作原理

Sentinel核心分为三个部分

  • 工作流程
  • 数据结构
  • 限流算法
    *
  • NodeSelectorSlot:负责收集资源调用路径,艺术装结构存储调用栈,用于根据调用路径来限流降级
  • ClusterBuiderSlot,负责创建一资源名维度统计的ClusterNode,以及创建每个ClusterNode下按调用来源origin划分StatisticNode
  • LogSlot:出现限流、熔断、系统保护时负责记录日志
  • AuthoritySlot:权限控制,支持黑名单和白名单两种策略
  • SystemSlot:控制总入口流量,限制条件一次是QPS、总线程数、RT阈值、操作系统但钱Load1、操作系统当前CPU利用率
  • FlowSlot:根据限流规则和各个Node中统计数据进行限流判断
  • DegradeSlot:根据熔断规则和各个Node中的统计数据进行服务降级
  • StatisticSlot:统计不同维度的请求数、通过数、限流数、线程数等runtine信息,这些数据存储在DefaultNode、OriginNode和ClusterNode中
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

1999

每人一点点,明天会更好

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值