badgateway(手机网络错误502怎么解决)

简介上一篇文章《限流实施1》已经介绍了三种限流方案。随机拒流计数器方式基于滑动时间窗口限流剩下的本来打算马上写完,没想到三个月过去了,很尴尬。这次主要实现以下两

简介

上一篇文章《限流实施1》已经介绍了三种限流方案。

随机拒流计数器方式基于滑动时间窗口限流

剩下的本来打算马上写完,没想到三个月过去了,很尴尬。这次主要实现以下两个算法。

令牌桶算法漏斗算法

算法的具体实现可以在github上查看,网址为https://github . com/shidawuhen/asap/tree/master/controller/limit。

我们先来介绍一下这两个算法。

令牌桶算法算法说明

令牌桶算法:它是网络流量整形和速率限制中最常用的算法。令牌桶算法的原理图如下:

badgateway(手机网络错误502怎么解决)

一般流程是:

A.以特定速率向令牌桶传送令牌

b .根据预先设置的匹配规则对报文进行分类,不符合匹配规则的报文不经过令牌桶直接发送;

C.如果消息满足匹配规则,它需要令牌桶进行处理。当桶中有足够的令牌时,消息可以继续发送,令牌桶中的令牌量根据消息的长度相应减少;

D.当令牌桶中令牌不足时,无法发送消息,只有在桶中生成新令牌时才能发送消息。这样可以限制消息的流量小于或等于令牌生成的速度,从而达到限制流量的目的。

具有固定大小的令牌桶可以以恒定的速率连续生成令牌。如果代币没有被消耗,或者消耗的速度小于产生的速度,代币将一直增加,直到桶被填满。稍后生成的令牌将从桶中溢出。在最后一个桶中可以保存的最大令牌数永远不会超过桶的大小。

令牌桶可以允许突发,因为令牌桶一般有两个值,一个是桶容量,一个是单位时间内的令牌数量。如果桶容量大于单位时间内的令牌量,而单位时间内的消费小于该量,则令牌数最终会达到最大桶容量。此时,如果大量请求到达,所有令牌都会被消耗,从而实现允许突发的效果。

算法实现

算法有几个核心点。

因为要更新令牌数量,所以需要加锁定时向桶中放入令牌,有两种方式,一种是起goroutine,定时投放,另一种是在判断是否还有足够令牌的时候,根据投放情况进行投放。这次实现使用的是第二种方法,整个架构会更简单一些。

包限制导入(& # 34;github.com/gin-gonic/gin" & # 34;net/http & # 34;"同步& # 34;"时间& # 34;)//@ Tags limit//@ Summary token bucket拒绝流//@ produce Jon//@ success 200 { string } string & # 34;将成功返回ok & # 34//@失败502 & # 34;拒绝&#34失败& # 34;//@ router/limit/token reject[get]type token bucket struct { rate int 64//Fixed token in rate,R/s capacity int 64//bucket capacity tokens int 64//bucket last tokensec int 64//最后一个令牌放入bucket的时间戳slock sync . mutex } func(l * token bucket)allow()Bool { l . lock()defender l . lock . unlock()now:= time . now()。UNIX()l . tokens = l . tokens+(now-l . last token)* l.rate//Add该令牌if l . tokens >;l . capacity { l . tokens = l . capacity } l . last tokensec = now if l . tokens & gt;0 {//有令牌,收集令牌l . tokens-return true } else {//如果没有令牌,则拒绝return false } } func(l * token bucket)set(r,c int 64){ l . rate = r l . capacity = c l . tokens = 0 l . last tokensec = time。现在()。UNIX()} func CreateTokenBucket()* token bucket { t:= & token bucket { } t . Set(1,5)return t } var token bucket * token bucket = CreateTokenBucket()func token reject(c * gin。上下文){ //fmt。Println(tokenBucket.tokens) if!tokenBucket。Allow() { c.String(http。StatusBadGateway,& # 34;拒绝& # 34;)返回} c.String(http。StatusOK,& # 34;好& # 34;)}漏桶算法表明,当漏桶用作计量器时,可以用于流量整形和流量监管。漏桶的描述如下:

一个固定容量的漏桶,按照常量固定速率流出水滴;如果桶是空的,则不需流出水滴;可以以任意速率流入水滴到漏桶;如果流入水滴超出了桶的容量,则流入的水滴溢出了(被丢弃),而漏桶容量是不变的。

漏桶法很好理解。假设我们有一个水桶,它以固定的速度向下落一滴水。不管有多少请求,不管请求速率是多少,都会以固定的速率流出。与系统相对应的,是以固定的速率处理请求。

示意图如下:

badgateway(手机网络错误502怎么解决)

算法实现

查阅相关资料后,主要有三种算法。了解了这些实现之后,不知道是不是自己理解错了。感觉还不如数数拒流方便好用。如果我理解错了,你也可以告诉我。

这三种方式是:

令牌桶算法变种

桶的大小是单位时间内可以流出的最大数量,所以这个不写了。

计数拒流变种

此方法在指定时间将available 空设置为初始值。

包限制导入(& # 34;fmt & # 34"github.com/gin-gonic/gin" & # 34;net/http & # 34;"同步& # 34;"时间& # 34;)键入LeakyBucket struct {//capacity capacity int64 //剩余大小int 64//下次重置容量时间重置时间。Time //重置容量间隔ratetime。持续时间mutexsync。mutex} Fun (b *漏桶)Allow()Bool { b . mutex . lock()Defer b . mutex . unlock()if time . now()。after(b . reset){//b . reset = time . now()。Add (b.rate)需要重置。更新时间b . remaining = b . capacity//reset remaining capacity } fmt . println(b . remaining)if b . remaining >:0 {//判断是否可以通过b . remaining-return true } return false } func(b * Leaky bucket)set(r time。持续时间,c int64) { b .速率= r b .容量= c b .剩余= c b .重置=时间。现在()。add(b . rate)} func CreateLeakyBucket(r time。Duration,c int 64)* leaky bucket { t:= & leaky bucket { } t . Set(r,c)return t } var leaky bucket * leaky bucket = CreateLeakyBucket(time。Second*2,10)func leak对象(c *gin。上下文){ if!leakyBucket。Allow() { c.String(http。StatusBadGateway,& # 34;拒绝& # 34;)返回} c.String(http。StatusOK,& # 34;好& # 34;)}真固定费率算法的实现基于uber团队的开源github.com/uber-go/ratelimit。

这种实现保证了如果有大量请求,每个请求将在指定的时间间隔执行。如果1s设置为处理100个请求,则每10ms处理一个请求。

如果长时间没有请求,短时间内仍然会处理请求。当然,这种情况很容易解决。可以想想怎么修改。

包限制导入(& # 34;fmt & # 34"github.com/andres-erbsen/clock" & # 34;github.com/gin-gonic/gin" & # 34;net/http & # 34;"同步& # 34;"时间& # 34;)//真固定速率typeclock接口{ now()time . time sleep(time . duration)} type limiter结构{ sync . mutex//上次锁定。时间//最后一次的睡眠。持续时间//等待时间per请求时间。持续时间//时间间隔最大松弛时间。Duration //最大剩余时钟Clock // clock}// Take将阻塞两个请求之间的时间。//Take调用的平均次数是time.Second/rate.func(t * limiter)Take()time . time { t . lock()defer t . unlock()now:= t . clock . now()//如果是第一次请求就释放If t . last . is zero(){ t . last = now return t . last }//sleep for根据perRequest和最后一次请求的时间计算应该休眠的时间//由于每次请求的间隔可能超过perRequest,所以这个数可能是负数 并累加t . sleepFor+= t . Per Request-now sub(t . Last)fmt . println(t . sleep for)//我们不应该把sleep for做得太负,因为这意味着一个服务在短时间内慢很多,之后会得到更高的RPS。 如果t.sleepFor & ltt . max slack { t . sleepFor = t . max slack }//如果sleep for为正,则sleep If t . sleep for >:0 { t . clock . sleep(t . sleep for)t . last = now。add(t . sleep for)t . sleep for = 0 } else { t . last = now } return t . last } func new limiter(rate int)* limiter { l:= & limiter { perRequest:time。秒/时间。持续时间(速率),maxSlack: -10 *时间。秒/时间。Duration(rate),} if l . clock = = nil { l . clock = clock . new()} return l } var rl = new limiter(100)//每秒100个请求funcleakrejectfixed rate(c * gin . context){ prev:= time . now()for I & lt;10;i++ {现在:= rl。Take() fmt。Println(我,现在。sub(prev))prev = now } c . String(http。StatusOK,& # 34;好& # 34;)}演示结果如下:

badgateway(手机网络错误502怎么解决)

总结

学习了令牌桶和漏桶,结合这几年工作中的具体场景,感觉令牌桶算法的实用价值更大。

下面是令牌桶和漏桶的比较:

令牌桶是按照固定速率往桶中添加令牌,请求是否被处理需要看桶中令牌是否足够,当令牌数减为零时则拒绝新的请求;漏桶则是按照常量固定速率流出请求,流入请求速率任意,当流入的请求数累积到漏桶容量时,则新流入的请求被拒绝;令牌桶限制的是平均流入速率(允许突发请求,只要有令牌就可以处理,支持一次拿3个令牌,4个令牌),并允许一定程度突发流量;漏桶限制的是常量流出速率(即流出速率是一个固定常量值,比如都是1的速率流出,而不能一次是1,下次又是2),从而平滑突发流入速率;令牌桶允许一定程度的突发,而漏桶主要目的是平滑流入速率;两个算法实现可以一样,但是方向是相反的,对于相同的参数得到的限流效果是一样的。

最后给大家看一下各种限流算法的对比。

badgateway(手机网络错误502怎么解决)

资料限频方案比较https://www.cnblogs.com/moodlxs/p/10337511.html高并发系统限流-漏桶算法和令牌桶算法https://www.cnblogs.com/xuwc/p/9123078.html令牌桶与漏桶算法https://blog.csdn.net/qq_17612199/article/details/86984067漏桶、令牌桶限流的Go语言实现https://www.cnblogs.com/liwenzhou/p/13670165.html

最后

如果你喜欢我的文章,可以关注我的微信官方账号(程序员麻辣烫)

我的个人博客是https://shidawuhen.github.io/.

以前文章的回顾:

技术

秒杀系统分布式系统与一致性协议微服务之服务框架和注册中心Beego框架使用浅谈微服务TCP性能优化限流实现1Redis实现分布式锁Golang源码BUG追查事务原子性、一致性、持久性的实现原理CDN请求过程详解常用缓存技巧如何高效对接第三方支付Gin框架简洁版InnoDB锁与事务简析算法总结

阅读笔记

敏捷革命如何锻炼自己的记忆力简单的逻辑学-读后感热风-读后感论语-读后感孙子兵法-读后感

项目流程管理对项目管理的一些看法对产品经理的一些思考关于程序员职业发展的思考关于代码review的思考Markdown编辑器推荐-typora

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。

作者:美站资讯,如若转载,请注明出处:https://www.meizw.com/n/176103.html

发表回复

登录后才能评论