本文的github地址点击这里

获取时间窗口的主要流程

在 Sentinel 中,主要是通过 LeapArray 类来实现滑动时间窗口的实现和选择。在 sentinel 的这个获取时间窗口并为时间窗口添加指标的过程中,主要的流程为:

  • 根据当前时间选择当前时间应该定位当前时间应该属于的时间窗口 id。
  • 根据时间窗口 id 获取时间窗口。这里可能会存在三种情况:
  1. 时间窗口还未建立,那么将会为此次流量的进入建立一个新的时间窗口返回,并且接下来这个时间窗口内的获取请求都将返回该窗口。
  2. 时间窗口已经建立的情况下,将会直接获取已经存在的符合条件的时间窗口。
  3. 时间窗口可能已经存在,但是当前获取的时间窗口已经过期,需要加锁,并重置当前时间窗口。
  4. 当前进入的时间已经远远落后当前的时间,目标时间窗口已经被 reset 更新成更新的时间窗口,那么将不会返回目标时间窗口,而是返回一个新的空的时间窗口进行统计,这个时间窗口不会再被重复利用。
    其中的第四个情况表明,sentinel 的滑动时间窗口是有时间范围的,这也是为了尽量减少 sentinel 的所占用的内存,默认情况下 sentinel 的采取的时间长度为 1 分钟和 1 秒钟。这里的实现与 LeapArray 类的结构非常有关系。
    protected final AtomicReferenceArray<WindowWrap<T>> array;

在 LeapArray 中,时间窗口的存放通过一个由 AtomicReferenceArray 实现的 array 来实现。AtomicReferenceArray 支持原子读取和写入,并支持通过 cas 来为指定位置的成员进行更新。在时间窗口的创建并放回 array 的过程中,也就是上文的第一步,就是通过 AtomicReferenceArray 的 compareAndSet()方法来实现,保证并发下的线程安全。并发情况下,通过 cas 更新失败的线程将会回到就绪态,在下一次婚欢得到已经初始化完成的时间窗口。

    private final ReentrantLock updateLock = new ReentrantLock();

此处的 updateLock 是专门在上述的第三个情况来进行加锁的,只有成功得到锁的线程才会对过期的时间窗口进行 reset 操作,其他没有成功获取的线程将不会挂起等待,而是通过 yield()方法回到就绪态在下一次的循环尝试重新获取该位置的时间窗口。在下一次获取该锁的线程可能已经完成了,那么将会执行上述第二步,否则继续回到就绪态等待下一次循环中再次获取该时间窗口。
以上两个数据结构是 LeapArray 类实现时间窗口在高并发下准确获取时间窗口并更新的关键。

以秒级别的时间窗口举个例子

在 sentinel 默认的秒级别时间窗口中,array 的大小为 2,也就是每 500ms 为一个时间窗口的大小。
因此当一个线程试图获取一个时间窗口来记录指标数据的时候,将会根据单个时间窗口的时间跨度进行取模,来得到 array 上对应的时间窗口的下标,在这个情况下,将为 0 或者 1,之后计算当前线程时间指标所属的时间窗口的起始时间,以此为依据来判断如果在后面如果获取到的时间窗口是过期还是正好所需要的。
最后,将会不断循环从 array 尝试获取之前计算得到下标位置处的时间窗口,可能发生的 4 种情况如上所示。在这个情况,如果 cas 失败或事没有尝试获取到更新锁,都不会阻塞或是挂起,而是通过 yield 重新回到就绪态等待下一次循环获取。

时间窗口本身的线程安全指标更新

在指标集合类的实现 MetricBucket 中,通过 LongAdder 类来记录单个指标的值而不是 AtomicLong,LongAdder 内部的核心思路是为各个线程分配一个专属变量进行更新,在需要总数的时候对这一系列进行累加,因此在更新值的时候相比 AtomicLong 会尽可能减少线程间的竞争,达到高效的 metric 更新。

sentinel 时间窗口的实现相关推荐

  1. sentinel 时间窗口_Sentinel使用令牌桶实现预热【原理源码】

    前言 Sentinel的QPS流控效果有快速失败.预热模式.排队等待.预热+排队等待模式,本文主要分析预热模式中是如何使用令牌桶算法限流的. 一.流控效果源码结构 在FlowRule更新缓存时,根据配 ...

  2. sentinel 时间窗口_Sentinel潜龙勿用篇

    前言 我为什么写这篇文章,是因为Sentinel实在是太强大太好用了,再加上阿里开源,Sentinel的发展迅猛.已有多家公司生产使用,但但凡神功,一个不慎,就有可能走火入魔,轻则离职走人,重则走火入 ...

  3. sentinel 时间窗口_Sentinel滑动窗口算法

    在前面搞清楚了Sentinel的使用后,大致理了一下Sentinel的责任链,搞清楚了这个,基本就已经梳理清楚sentinel-core模块的大部分内容,顺着这条链路可以继续梳理很多东西. 知其然.知 ...

  4. sentinel 时间窗口_Sentinel 实战-规则持久化

    规则持久化的5种方式 规则丢失 无论是通过硬编码的方式来更新规则,还是通过接入 Sentinel Dashboard 后,在页面上操作来更新规则,都无法避免一个问题,那就是服务重新后,规则就丢失了,因 ...

  5. sentinel滑动时间窗口算法学习

    滑动时间窗口 先不说sentinel的算法实现,先说什么是滑动时间窗口, 我们在进行限流的时候,比如通过QPS进行限流,那假如我们以秒为单位,举个例子: 我设置了限流规则,qps是10 如果不使用滑动 ...

  6. sentinel 滑动时间窗口算法

    sentinel 滑动时间窗口的算法 为什么要用滑动时间窗口算法? 互联网中最常见的一个问题:限流,即在一段时间内,限制访问某个接口的请求数. 要实现限流(或熔断降级),方法有很多,最基本的如计数器法 ...

  7. Sentinel 滑动窗口实现原理 侵删

    要实现限流.熔断等功能,首先要解决的问题是如何实时采集服务(资源)调用信息.例如将某一个接口设置的限流阔值 1W/tps,那首先如何判断当前的 TPS 是多少?Alibaba Sentinel 采用滑 ...

  8. 2021年大数据Spark(五十二):Structured Streaming 事件时间窗口分析

    目录 事件时间窗口分析 时间概念 ​​​​​​​event-time ​​​​​​​延迟数据处理 ​​​​​​​延迟数据 ​​​​​​​Watermarking 水位 ​​​​​​​官方案例演示 事件 ...

  9. Java 实现滑动时间窗口限流算法,你见过吗?

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 作者 | dijia478 来源 | https://w ...

最新文章

  1. mysql 7.4_CentOS 7.4 64位/ mysql
  2. 2022我会成为高手吗
  3. jsoup HTML parser hello world examples--转
  4. ASP.NET应用程序设计的10大技巧
  5. 模仿百度搜索框,进行联想搜索
  6. Python运维-获取当前操作系统的各种信息
  7. CheckedListBox扩展方法代码
  8. 软件过程改进之百科名片
  9. dense rank改为mysql_mysql上排名sql的写法,类似oracle的rank和dense
  10. vb mysql 插入记录_vb实现数据库的连接,修改,删除,插入(ADO.Net)
  11. Debian中proftpd+mysql+虚拟用户+匿名用户+磁盘限额的配置
  12. 2021年了!!Xshell7新手下载和安装教程(步骤超详细),以及远程与虚拟机连接
  13. python图片表格转excel表格_python提取图片内容并转换成对应表格的markdown代码
  14. Windows USB功能驱动开发总结
  15. linux CentOS7虚拟机修改静态ip地址
  16. 【java】英语单词对战小游戏
  17. 基于单片机的CO2温湿度电路设计(#0217)
  18. cmd导入导出mysql中的数据库为sql文件
  19. react 学习(三) 组件更新
  20. Windows搭建FTP服务器,JAVA实现读写功能

热门文章

  1. 程序代码移植和烧录需要注意什么_法人变更需要注意什么
  2. 二叉树最简单的遍历方式——二叉树的层序遍历
  3. 泉州中考分数如何计算机,2019年泉州中考总分多少分,泉州中考考试科目设置
  4. 【Linux】使用du、df 和 sort 命令快速找出Linux系统中的大文件
  5. 解决Oracle 本地可以连接,远程不能连接问题
  6. URL加载系统之三:NSURLConnection
  7. mysql 几种插入数据的方法
  8. iOS--百度地图相关功能的实现
  9. vagrant打造自己的开发环境~~我也来一发
  10. DocBook vs Apache Forrest