暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

sentinel-服务高可用架构(限流篇)

渣渣笔记 2021-08-11
1136

什么是服务限流?

当服务系统资源不够,无法承载大量请求时,需要对系统按照一定的规则进行流量限

为什么需要服务限流?

系统承载的访问量是有限的,如果不做流量控制,会导致系统资源占满,服务超时,在微服务体系中就有可能引起服务瘫痪和整体不可用的现象

sentinel是什么?

sentinel是面向分布式服务架构的轻量级的流量控制产品

sentinel的基本发展过程:

  • 2012年 sentinel诞生于阿里巴巴,
  • 2013-2018年 sentinel在集团内部快速发展,覆盖了大部分的应用场景,
  • 2018年 sentinel开源

sentinel 能做什么?

流量控制

熔断

降级

系统负载保护

本文章主要介绍利用sentinel来实现流控的能力。

qps限流方式

  • 集群限流(集群均摊模式)

    集群限流,在sentinel中,有两种身份,

    在sentinel的集群流控上,又分为两种情况

    http://mutou.qklchain.com/share/bZlefF.png
    http://mutou.qklchain.com/share/tQWSfp.png

    相比于集体均摊的限流模式,单机均摊模式,无需单独部署tokenserver,无需和tokenserver保持通讯,所以减少了请求的时间损耗,不过实际情况是到每台机器的流量不是均匀的,所以单机流量无法像集群均摊模式一样准确的限制集群流量,导致总量没到的情况下,某台机器就开始了限流

    • 单机均摊模式,限制某个资源在单台服务器上的qps,此方式的tokenserver可以和应用进程同时部署,比如现在有4个client连接到了sentinel server,每个client的均摊阈值时10,那么集体均摊的限流控制是4*10=40个,如下图
    • 集体均摊模式,限制某个资源的整体qps,此时的tokenserver需要单独部署,比如可以配置集群qps限流控制为40,此时每次的qps请求都要经过tokenserver进行验证,如下图:
  1. tokenclient 用于向tokenServer请求token
  2. tokenServer负责处理tokenclient的请求,并根据配置的集群信息判断是否需要发放token

并发数限流方式

线程池限流:

在sentinel中,主要基于线程池技术来实现并发数限流,针对于某个资源,会隔离出一些线程,sentinel会控制当前资源的使用线程数,当超过请求时给与拒绝或者等待,直到堆积的线程处理完成线程池限流方式的优点是隔离线较强

优点:资源线程相互隔离,减少了依赖服务之间的互相影响

缺点:线程数量过多,会导致线程上下文的overhead比较大,所以尤其会对低延迟的服务禅城一定的影响

http://mutou.qklchain.com/share/wiVGVm.png

并发数(信号量)限流:

基于线程数限流,则不需要创建和管理线程池,而是简单的统计当前资源的上下文的线程数据,如果超过阈值,则进行拒绝处理

sentinel是如何实现qps限流的?

sentinel实现限流的核心是一套责任链模式

ProcessorSlot 是一个父类,所有的责任链和SLot都实现了ProcessorSlot,责任链的entry会一次执行责任链的各个slot

在sentinel我们常用的slot有下面集中:

  • StatisticSlot(StaticsticSlot主要负责统计资源调用情况)
  • flowSlot(主要负责基于统计资源做限流规则验证)

sentinel的滑动窗口实现基于leapArray,核心关注几个参数

时间窗口长度(ms windowLengthMs)

窗口长度(sampleCount)

时间间隔(intervalInMs)

窗口开始时间 = 当前时间(ms)-当前时间(ms)%时间窗口长度(ms)

比如:

intervallInMs=1000ms, sampleCount=2, 那么windowLengthMs=500ms

intervallInMs=60s,sampleCount=60,那么windowLengthMs=1s

获取当前时间戳下的时间id的方法

long timeId = time / windowLength

int idx = (int)(timeId % array.length());

其中time为当前时间,array是时间窗口数量

  • 如果获取到的时间窗口自为空,则新建时间窗口
  • 如果获取到的时间窗口非空,且时间窗口开始时间=计算的开始时间,说明当前时间正好在这个时间窗口里,直接返回当前窗口。
  • 如果获取到的时间窗口非空,且时间窗口的开始时间小于我们计算的开始时间,说明时间窗口已经过期(距离上次获取时间窗口已经过去比较久的场景),需要更新时间窗口(CAS加锁操作),将时间窗口的开始时间设为计算出来的开始时间,将时间窗口里的计数器重置为0,

时间窗口内部的计数器,主要记录以下信息

  • 通过计数
  • 阻塞计数
  • 异常计数
  • 成功计数
  • 响应rt

以上几个数都是在sentinel  StaticsicSlot中的entry和exist函数中记录

而flowSlot用于做两件事情

  • 获取资源对应的限流规则
  • 根据限流规则判断是否被限流

如果对改文章内容某些细节不了解,可以继续阅读sentinel的源代码,或者直接联系 老k聊架构


文章转载自渣渣笔记,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论