Sentinel 万字教程.docx

上传人:lao****ou 文档编号:137066 上传时间:2023-04-10 格式:DOCX 页数:29 大小:390.60KB
下载 相关 举报
Sentinel 万字教程.docx_第1页
第1页 / 共29页
Sentinel 万字教程.docx_第2页
第2页 / 共29页
Sentinel 万字教程.docx_第3页
第3页 / 共29页
Sentinel 万字教程.docx_第4页
第4页 / 共29页
Sentinel 万字教程.docx_第5页
第5页 / 共29页
亲,该文档总共29页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《Sentinel 万字教程.docx》由会员分享,可在线阅读,更多相关《Sentinel 万字教程.docx(29页珍藏版)》请在第一文库网上搜索。

1、Sentinel万字教程限流作为现在微服务中常见的稳定性措施,在面试中肯定也是经常会被问到的,我在面试的时候也经常喜欢问一下你对限流算法知道哪一些?有看过源码吗?实现原理是什么?第一部分先讲讲限流算法,最后再讲讲源码的实现原理。限流算法关于限流的算法大体上可以分为四类:固定窗口计数器、滑动窗口计数器、漏桶(也有称漏斗,英文Leaky bucket)、令牌桶(英文 Token bucket)o固定窗口,相比其他的限流算法,这应该是最简单的一种。它简单地对一个固定的时间窗口内的请求数量进行计数,如果超过请求数量的阈值,将被直接丢弃。这个简单的限流算法优缺点都很明显。优点的话就是简单,缺点举个例子来

2、说。比如我们下图中的黄色区域就是固定时间窗口,默认时间范围是60s,限流数量是100o如图中括号内所示,前面一段时间都没有流量,刚好后面30秒内来了 1 00个请求,此时因为没有超过限流阈值,所以请求全部通过,然后下一个窗口的20秒内同样通过了 100个请求。所以变相的相当于在这个括号的40秒的时间内就通过了 200个请求,超过了我们限流的阈值。60s, B艮流 100限流为了优化这个问题,于是有了滑动窗口算法,顾名思义,滑动窗就是时间窗口在随着时间推移不停地移动。滑动窗口把一个固定时间窗口再继续拆分成N个小窗口,然后对每个小窗口分别进行计数,所有小窗口请求之和不能超过我们设定的限流阈值。以下

3、图举例子来说,假设我们的窗口拆分成了 3个小窗口,小窗口都是20s,同样基于上面的例子,当在第三个20s的时候来了 100个请求,可以通过。然后时间窗口滑动,下一个20s请求乂来了 100个请求,此时我们滑动窗口的60s范围内请求数量肯定就超过100 了啊,所以请100Leaky bucket漏桶算法,人如其名,他就是一个漏的桶,不管请求的数量有多少,最终都会以固定的出口流量大小匀速流出,如果请求的流量超过漏桶大小,那么超出的流量将会被丢弃。也就是说流量流入的速度是不定的,但是流出的速度是恒定的。这个和MQ削峰填谷的思想比较类似,在面对突然激增的流量的时候,通过漏桶算法可以做到匀速排队,固定速

4、度限流。漏桶算法的优势是匀速,匀速是优点也是缺点,很多人说漏桶不能处理突增流量,这个说法并不准确。漏桶本来就应该是为了处理间歇性的突增流量,流量一下起来了,然后系统处理不过来,可以在空闲的时候去处理,防止了突增流量导致系统崩溃,保护了系统的稳定性。但是,换一个思路来想,其实这些突增的流量对于系统来说完全没有压力,你还在慢慢地匀速排队,其实是对系统性能的浪费。所以,对于这种有场景来说,令牌桶算法比漏桶就更有优势。令牌桶令牌桶算法是指系统以一定地速度往令牌桶里丢令牌,当一个请求过来的时候,会去令牌桶里申请一个令牌,如果能够获取到令牌,那么请求就可以正常进行,反之被丢弃。现在的令牌桶算法,像Guav

5、a和Sentinel的实现都有冷启动/预热的方式,为了避免在流量激增的同时把系统打挂,令牌桶算法会在最开始一段时间内冷启动,随着流量的增加,系统会根据流量大小动态地调整生成令牌的速度,最终直到请求达到系统的阈值o源码举例我们以s e n t i n e 1举例,sentinel中统计用到了滑动窗口算法,然后也有用到漏桶、令牌桶算法。sentinel中就使用到了滑动窗口算法来进行统计,不过他的实现和我上面画的图有点不一样,实际上sentinel中的滑动窗口用一个圆形来描述更合理一点。前期就是创建节点,然后slot串起来就是一个责任链模式,Statist icSlot通过滑动窗口来统计数据,Flo

6、wSlot是真正限流的逻辑,还有一些降级、系统保护的措施,最终形成了整个sentinelSlot chainRuntime statisticsStatisticSlotTimestamp 1527574049ActionSystemSlotAuthorizeslot |DegradeSlot |FlowSlotrules就看看官方图吧,这圆形画起来好恶心滑动窗口的实现主要可以看LeapArray的代码,默认的话定义了时间窗口的相关参数。对于sent inel来说其实窗口分为秒和分钟两个级别,秒的话窗口数量是2,分钟则是60个窗口,每个窗口的时间长度是1 s ,总的时间周期就是60s ,分成6

7、0个窗口,这里我们就以分钟级别的统.protected int windowLengthlnMs;protected int samplrCo”ntprotected int interval InMsprivate double interval InSecond ;protected final AtomicReferenceArrayWindowWrap array;然后我们要看的就是它是怎么计算出当前窗口的,其实源码里写的听清楚的,但是如果你按照之前想象把他当做一条直线延伸去想的话估计不太好理解。首先计算数组索引下标和时间窗口时间这个都比较简单,难点应该大部分在于第三点窗口大于old这

8、个是什么鬼,详细说下这几种情况。1. 数组中的时间窗口是是空的,这个说明时间走到了我们初始化的时间之后了,此时new一个新的窗口通过CAS的方式去更新,然后返回这个新的窗口就好了。2. 第二种情况是刚好时间窗口的时间相等,那么直.接返回,没啥好说的3. 第三种情况就是比较难以理解的,川.以参看两条时间线的图,就比较好理解了,第一次时间窗口走完了达到1200,然后圆形时间窗口开始循环,新的时间起始位置还是1200,然后时间窗口的时间来到1676, B2的位置如果还是老的窗口那么就是600,所以我们要重置之前的时间窗口的时间为当前的时间。4.最后一种一般情况不太可能发生,除非时钟回拨这样子从这个我

9、们可以发现就是针对每个Wi ndowWrap时间窗口都进行了统计,最后实际上在后面的几个地方都会用到时间窗口统计的QPS结果,这里就不再赘述了,知道即可。rivate int calculateTimeldx /*Vaid*/ 1 ong timeMi 11 is)long timeld = timeMillis / windowLengthlnMs;/ Calculate curren t index so we can map the timestathe leap array.return (int) (timeld % array.length ();rotected long cal

10、culateWindowStart ( id*/ long timeMi11 is)return timeMi His - timeMi1lis % windowLengthlnMs;ublic WindowWrap currentwindow (long timeMillis)/当前时间如果小于0,返回空rp 1 ur:i nil i I/计算时间窗口的索弓iint idxcalculateTimeldx(timeMi11 is);计算当前时间窗U的开始时间1 ong windowStart = calculateWindowStart (timeMi11 is);while (true)/

11、在窗口数组中获得窗口WindowWrap old = array.get (idx);Bi* 200BOBlB2 NULL4006008001001200time st ami:time=8if (old = null) *比如当前时间是888,根据计算得到的数组窗口位置是个空.WindowWrap window = new WindowWrap(wind)wLengthInMs, windowStart, newEmptyBucket (timeMi11 is);if (array-compareAndSet (idx, null, window)Successfully upda ted,

12、 re turn thecreated bucket.return window;elseContention failed, the thread wi 11 yield i tstime slice to wai t for bucket available.Thread, yield ();else if (windowStart = old.windowStart()81*这个更好了,刚好等于,直接返回就有return old;else if (windowStart old.windowStart ()BOBlB2B3B4* 200400600800100C1200time st a

13、mi:BOBlB2NULLB4=1676*这个要当成圆形理解就好了,之前如果是1200一个完整的匾* 窗口开始时间是1600,获取到的old时间其实会是I ,(lip(hi I rLock, t ry Lock () ) ISuccessfully get the update lock, now we* .120014001600180020002200 t imes ta/n/reset the bucket.timewStart);return resetWindowTo (old, windo finallyupdateLock. unlock();else Thread, yield

14、 ();else if (windowStart old.windowStart这个不太可能出现,嗯。o时钟回拨return new WindowWrap(windowLengthlnMs, windowStart, newEmptyBucket (t imeMi His);s e n t i n e 1主要根据F 1 o w S 1 o t中的流控进行流量控制,其中Rat eLimiterControl ler就是漏桶算法的实现,这个实现相比其他几个还是简单多了,稍微看一下应该就明白了。1.首先计算出当前清求平摊到1s内的时间花费,然后去计算这一次请求预计2.时间如果小于当前时间的话,那么以当前时间为主,返回即可3.反之如果超过当前时间的话,这时候就要进行排队等待了,等待的时候要判断是否超过当前最大的等待时间,超过就直接丢弃4.没行超过就更新上一次的通过时间,然后再比较一次是否超时,还超时就重置时间,反之在等待时间范围之内的话就等待,如果都不是那就可以通过了publ i c class RateLi mi terControl1 er i mplements Traff i cShapingControlprivate final

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 应用文档 > 汇报材料

copyright@ 2008-2022 001doc.com网站版权所有   

经营许可证编号:宁ICP备2022001085号

本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有,必要时第一文库网拥有上传用户文档的转载和下载权。第一文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知第一文库网,我们立即给予删除!



客服