Alibaba 流量防卫兵Sentinel概述

Sentinel概述

分布式系统的流量哨兵,以流量为切入点,对比Redis的哨兵模式可以得出sentinel在微服务中的作用是对流量进行监控与管理,例如流量的控制,熔断降级,系统负载保护等。

由Sentinel的源码可以看出,Sentinel在对流量进行管控的时候是通过责任链的模式来处理的。在Restful中,将系统的一切定义为资源,sentinel在此处也借鉴了此种思想,将需要流量控制的一切当作资源,然后定义一系列的规则来对资源进行处理。

资源与规则

资源概述

虽然官网说资源可以是Java应用程序中的任何内容,通过对源码的阅读,从提供的注解和demo来看,对应资源的范围应该是指方法和代码片段。

责任链模式处理资源

虽然使用责任链模式可以做到请求与责任处理分离,但是由于使用链表来实现责任链,故不够灵活,对于所有的资源管控都需要一个完整的流程处理,存在性能损耗和可扩展性受限,如果可以使用跳表,针对不同的资源可以实现定制化规则会更完美。

备注:此处使用StatisticSlot进行统计的时候,可能会存在高并发的问题;如果进行日志记载的时候抛出异常,也会影响业务的执行。 

规则概述

Sentinel有提供3种规则或者说是策略来对资源进行管控,存在管控台可以动态实时调整:

系统保护规则SystemRule

漏桶算法来进行流量塑型;包括系统负载,AvgRt,Qps,最大线程数等粒度。

备注:注意是否存在流量兜底和请求丢失? 

流量控制规则FlowRule

(a)并发数控制的立即拒绝和QPS流量控制:

QPS的控制行为:0直接拒绝default,1冷启动warm up,2匀速器rate limiter

(b)通过调用关系的限流:调用方限流,链路限流和关联流量控制

NodeSelectorSlot建立不同资源间的调用的关系,通过ClusterNodeBuilderSlot记录每个资源的实时统计信息

 备注:流量的控制应该同ClusterNodeBuilderSlot和StatisticSlot存在直接的关系,如果任何Slot的统计数据存在问题,则流量控制是不精准的,不过这种精准性的要求应该是存在滑动空间是可以妥协的。限流的规则可以是多种多样的,可以对资源使用多种限流规则。

熔断降级规则DegradeRule

并发线程数控制,异常比例ExceptionRatio和响应时间RT控制。

针对RT而言,准降级状态触发后,连续5个时间窗口依旧超过限流阈值,会进行降级处理。

针对异常比例,不存在准降级状态的触发,直接进行降级处理。

规则加载

1、所有的规则都可以通过对应的硬编码模式XxxRuleManager来加载

2、可以在内存中通过动态的修改生效,通过API来进行修改

3、Sentinel有提供通过实现DataSource接口的方式来定义规则的存储

可通过配置中心的获取,通过Redis和Zookeeper获取,通过数据库和文件获取。

 DataSource概述

DataSource的推模式,需要继承抽象类AbstractDataSource,实现readResource()方法,需要在构造方法中添加监听器。

DataSource的拉模式,需要继承抽象类AutoRefreshDataSource,实现readResource()方法即可。

最后将数据源注册到规则管理器中。

Entry概述

由源码可知,所有需要被保护的相关资源都需要被Entry给包围起来,如果任何设置的规则在请求达到临界值时都会被blocked,然后返回false和抛出BlockException。

Entry存在侵入业务代码的嫌疑,如果抛出内部异常会阻碍业务的运行。如果完全不侵入业务代码,估计框架也很难实现其功能,通常智能学习Spring来解决如何将影响降到最低。

Entry的进入和离开时成对出现的,要不然会抛出ErrorEntryFreeException异常,这点值得注意。对比ReentrantLock的进入与离开产生死锁而言,sentinel做的很人道。

SphU对资源的处理
Entry entry = null;

// 务必保证finally会被执行

try {
  // 资源名可使用任意有业务语义的字符串

  entry = SphU.entry("自定义资源名");

  /**  * 被保护的业务逻辑  */

} catch (BlockException e1) {
  // 资源访问阻止,被限流或被降级

  // 进行相应的处理操作

} finally {
  if (entry != null) {
    entry.exit();

  }

}

SphO对资源的处理
// 资源名可使用任意有业务语义的字符串

  if (SphO.entry("自定义资源名")) {
    // 务必保证finally会被执行

    try {
      /**      * 被保护的业务逻辑      */

    } finally {
      SphO.exit();

    }

  } else {
    // 资源访问阻止,被限流或被降级

    // 进行相应的处理操作

  }

总结
通常实际运用中使用try...catch的方式来对资源进行处理。Sentinel的功能还算比较齐全,它的使用难度和学习成本都不大。Sentinel对业务代码的侵入比较小,它依赖的jar包也不多,整体的代码量更是少的可怜。Sentinel是双十一抗流量的利器,也是完善Dubbo生态圈的重要组件。Sentinel也有提供DashBoard来查对应的指标输出和设置对应的规则,但是UI比较简陋。

 
 



 

你可能感兴趣的:(分布式)