Sentinel

  计数器算法:
    指定周期内限制最大值,到达下个周期时从0开始计数。
    缺陷:临界值问题00:01:59和00:02:01分别出现最大值的流量,导致这2s内总流量达到最大值流量的2倍

  滑动窗口算法(Sentinel采用此算法):
    滑动窗口的大小为若干个小时间窗的和,每个小时间窗可限x个请求,
    滑动窗口随着时间移动,滑动时间窗口的流量等于其包含的完整小时间窗中的流量和

  令牌桶限流算法:
    系统以恒定的速率生产令牌放到令牌桶中,若桶已满则不放,可应对突发流量
    每个请求处理前都需要从令牌桶中获取令牌,若获取不到则触发限流策略

  漏桶限流算法:
    系统维护一个固定大小的容器,同时以固定速率漏水
    每次请求时先看当前桶中的水满没满(当前水量=上次更新后的水量-时间跨度*漏水速率),满了就限流,没满就正常处理
    https://baijiahao.baidu.com/s?id=1666902623332115966&wfr=spider&for=pc
限流算法
Sentinel三种熔断策略:

  1. 平均响应时长:1s内累计有5个请求的平均响应时长超过阈值,触发熔断,在接下来的熔断时间窗内的请求直接降级
  2. 异常比例:1s内请求数>=5,且1s内异常请求数占总请求数的比例超过阈值,触发熔断,在接下来的熔断时间窗内的请求直接降级
  3. 异常数:1min内异常请求数超过阈值,触发熔断,在接下来的熔断时间窗内的请求直接降级
Sentinel三种熔断策略

流控的两种类型:QPS和线程数,QPS是资源每秒查询数,线程数是资源占用的线程上限,防止线程耗尽服务雪崩 P180

Sentinel Dashboard中配置的流控规则是存储于内存中的,Dashboard服务重启后规则全部丢失,需要集成动态数据源提供规则持久化功能

Sentinel集成Nacos作为数据源,实现动态流控:P190

  1. 在服务的application.yml文件中配置服务名、dashboard服务地址、数据源地址及指定配置的data-id、group-id、data-type、rule-type(流控、降级、热点、授权 P188)

  2. 登录Nacos Console,根据1中指定的配置参数创建配置,在配置内容中配置7项规则条件,即完成Sentinel规则的创建

{
    "resource": "/dynamic",        #资源名
    "limitApp": "default",        #针对来源
    "grade": 1,                    #阈值类型 1-QPS 0-线程数
    "count": 1,                    #单机阈值
    "strategy": 0,
    "controlBehavior": 0,
    "clusterMode": false         #是否集群
}
规则内容-7项

  3. 登录Sentinel Dashboard,2中创建的规则已自动加载

Sentinel集成Nacos作为数据源,在Nacos中修改流控规则后,Dashboard从Nacos中读取到的规则就是最新的
Sentinel Dashboard中修改流控规则后,Dashboard不支持自动同步到Nacos做持久化更新
Nacos作为配置中心,并没有Dashboard提供修改规则专用的UI界面,如果使用Nacos修改规则容易出错
Sentinel集成Nacos作为数据源存在哪些问题?

Dashboard进行规则的CRUD时,后台都是通过FlowControllerV1这个类进行处理

  还有一个FlowControllerV2类,有两个功能:

    1. DynamicRuleProvider:负责从数据源中拉取配置规则,在Dashboard中展示

    2. DynamicRulePublisher:负责将Dashboard中修改的规则推送给数据源,最持久化更新存储

修改Sentinel Dashboard源码,支持Dashboard-Nacos同步,步骤:

  1. 下载Sentinel Dashboard源码

  2. 创建FlowControllerV2中DynamicRuleProvider接口的实现类,重写getRules方法从Nacos中获取配置规则

  3. 创建FlowControllerV2中DynamicRulePublisher接口的实现类,重写publish方法,建立与Nacos的HTTP连接,将规则Post给它

  4. 在FlowControllerV2类注入DynamicRuleProvider和DynamicRulePublisher接口的上面,用@Qualifier指定2、3中的实现类名(首字母小写)

  5. 修改Dashboard的pom.xml中配置、一个html中将V1去掉

  6. 打jar包启动Dashboard

Sentinel处理链

  Slot链,责任链模式,比如LogSlot (日志处理槽) -> StatisticSlot (统计槽) -> ParamFlowSlot (根据统计槽的数据进行热点参数规则校验) ->

  FlowSlot (根据统计槽的数据进行流控规则校验) -> DegradeSlot (根据统计槽的数据进行降级规则校验)等

实时指标统计流程(StatisticSlot-StatisticNode实现统计)

  底层根据LongAdder.add()这种CAS操作进行累计请求通过数、线程数

  滑动计数器ArrayMetric,当进行累计时,先获取当前时间窗口,再做累计

  ArrayMetric中通过LeapArray来存储数据,是环形数据结构,只存储最近固定个数的时间窗口,过期的窗口内存会被覆盖

  LeapArray中获取当前时间窗对象的流程:

    先根据当前时间换算得到当前时间窗的下标,然后获取对应时间窗统计对象WindowWrap,这时有三种情况:

    1. 时间窗不存在,新建时间窗,并用CAS操作(只一次,不循环)添加到存储所有窗口的AtomicReferenceArray<WindowWrap<T>>原子数组的对应下标位置中

     1.1 若CAS成功,返回新建的时间窗

     1.2 若CAS失败,说明有其他线程在同时向原子数组的对应下标位置放新窗口,

        调用Thread.yeild()释放CPU占用,接着会进while继续判断,这时候一般就进入2.1的情况了

    2. 时间窗存在,然后判断这个时间窗的开始时间 与 当前时间换算得到的时间窗开始时间 是否相同

     2.1 若相同直接返回此时间窗

     2.2 若不相同证明时间窗已过期,使用ReentrantLock.tryLock()只尝试加一下锁,

        若拿到锁就重置窗口,若没拿到调用Thread.yeild()释放CPU占用,接着会进while继续判断,这时候一般就进入2.1的情况了

热点限流(ParamFlowSlot)

  场景:防止网络爬虫和恶意攻击,限制客户端IP,客户端IP地址就是一种热点参数;

     高并发修改数据库同一行,mysql需要加行锁,这行数据也是一种热点参数

  原理:滑动窗口算法+LRU策略(最近最少使用)实现热点参数的统计,LRU策略统计单位时间内最常访问的热点数据,滑动窗口统计每个参数的QPS

流量控制(FlowSlot)

  一个接口可以配置多个限流规则,有三种情况 P215:

    1. 不区分流量来源,对所有调用此接口的应用做整体限流

    2. 可针对同一个接口配置多个限流规则,每个规则配置不同的来源,可保证某些关键流量来源服务的并发量

    3. 配一个总体限流规则,在针对某个来源配置一个单独的限流规则,配合使用

服务降级(DegradeSlot)

  1. 请求达到DegradeSlot槽进行处理

  2. 先根据请求资源获取资源所有已配置的降级规则Set集合

  3. 对Set遍历,逐个进行降级校验,根据规则降级类型(平均响应时间、失败率、失败数),从StatisticNode中获取需要的统计数据进行计算并判断

原文地址:https://www.cnblogs.com/yfzhou528/p/13707080.html