当前位置: 首页 > news >正文

免费素材网站下载优秀网站建设平台

免费素材网站下载,优秀网站建设平台,四川网站建设培训班,网站开发没有完成 需要赔偿吗限流又称为流量控制#xff08;流控#xff09;#xff0c;通常是指限制到达系统的并发请求数#xff0c;本文列举了常见的限流策略#xff0c;并以gin框架为例演示了如何为项目添加限流组件。 限流 限流又称为流量控制#xff08;流控#xff09;#xff0c;通常是指…限流又称为流量控制流控通常是指限制到达系统的并发请求数本文列举了常见的限流策略并以gin框架为例演示了如何为项目添加限流组件。 限流 限流又称为流量控制流控通常是指限制到达系统的并发请求数。 我们生活中也会经常遇到限流的场景比如某景区限制每日进入景区的游客数量为8万人沙河地铁站早高峰通过站外排队逐一放行的方式限制同一时间进入车站的旅客数量等。 限流虽然会影响部分用户的使用体验但是却能在一定程度上报障系统的稳定性不至于崩溃大家都没了用户体验。 而互联网上类似需要限流的业务场景也有很多比如电商系统的秒杀、微博上突发热点新闻、双十一购物节、12306抢票等等。这些场景下的用户请求量通常会激增远远超过平时正常的请求量此时如果不加任何限制很容易就会将后端服务打垮影响服务的稳定性。 此外一些厂商公开的API服务通常也会限制用户的请求次数比如百度地图开放平台等会根据用户的付费情况来限制用户的请求数等。 常用的限流策略 漏桶 漏桶法限流很好理解假设我们有一个水桶按固定的速率向下方滴落一滴水无论有多少请求请求的速率有多大都按照固定的速率流出对应到系统中就是按照固定的速率处理请求。 漏桶法的关键点在于漏桶始终按照固定的速率运行但是它并不能很好的处理有大量突发请求的场景毕竟在某些场景下我们可能需要提高系统的处理效率而不是一味的按照固定速率处理请求。 关于漏桶的实现uber团队有一个开源的github.com/uber-go/ratelimit库。 这个库的使用方法比较简单Take() 方法会返回漏桶下一次滴水的时间。 import (fmttimego.uber.org/ratelimit )func main() {rl : ratelimit.New(100) // per secondprev : time.Now()for i : 0; i 10; i {now : rl.Take()fmt.Println(i, now.Sub(prev))prev now}// Output:// 0 0// 1 10ms// 2 10ms// 3 10ms// 4 10ms// 5 10ms// 6 10ms// 7 10ms// 8 10ms// 9 10ms }它的源码实现也比较简单这里大致说一下关键的地方有兴趣的同学可以自己去看一下完整的源码。 限制器是一个接口类型其要求实现一个Take()方法 type Limiter interface {// Take方法应该阻塞已确保满足 RPSTake() time.Time }实现限制器接口的结构体定义如下这里可以重点留意下maxSlack字段它在后面的Take()方法中的处理。 type limiter struct {sync.Mutex // 锁last time.Time // 上一次的时刻sleepFor time.Duration // 需要等待的时间perRequest time.Duration // 每次的时间间隔maxSlack time.Duration // 最大的富余量clock Clock // 时钟 }limiter结构体实现Limiter接口的Take()方法内容如下 // Take 会阻塞确保两次请求之间的时间走完 // Take 调用平均数为 time.Second/rate. func (t *limiter) Take() time.Time {t.Lock()defer t.Unlock()now : t.clock.Now()// 如果是第一次请求就直接放行if t.last.IsZero() {t.last nowreturn t.last}// sleepFor 根据 perRequest 和上一次请求的时刻计算应该sleep的时间// 由于每次请求间隔的时间可能会超过perRequest, 所以这个数字可能为负数并在多个请求之间累加t.sleepFor t.perRequest - now.Sub(t.last)// 我们不应该让sleepFor负的太多因为这意味着一个服务在短时间内慢了很多随后会得到更高的RPS。if t.sleepFor t.maxSlack {t.sleepFor t.maxSlack}// 如果 sleepFor 是正值那么就 sleepif t.sleepFor 0 {t.clock.Sleep(t.sleepFor)t.last now.Add(t.sleepFor)t.sleepFor 0} else {t.last now}return t.last }上面的代码根据记录每次请求的间隔时间和上一次请求的时刻来计算当次请求需要阻塞的时间——sleepFor这里需要留意的是sleepFor的值可能为负在经过间隔时间长的两次访问之后会导致随后大量的请求被放行所以代码中针对这个场景有专门的优化处理。创建限制器的New()函数中会为maxSlack设置初始值也可以通过WithoutSlack这个Option取消这个默认值。 func New(rate int, opts ...Option) Limiter {l : limiter{perRequest: time.Second / time.Duration(rate),maxSlack: -10 * time.Second / time.Duration(rate),}for _, opt : range opts {opt(l)}if l.clock nil {l.clock clock.New()}return l }令牌桶 令牌桶其实和漏桶的原理类似令牌桶按固定的速率往桶里放入令牌并且只要能从桶里取出令牌就能通过令牌桶支持突发流量的快速处理。 对于从桶里取不到令牌的场景我们可以选择等待也可以直接拒绝并返回。 对于令牌桶的Go语言实现大家可以参照github.com/juju/ratelimit库。这个库支持多种令牌桶模式并且使用起来也比较简单。 创建令牌桶的方法 // 创建指定填充速率和容量大小的令牌桶 func NewBucket(fillInterval time.Duration, capacity int64) *Bucket // 创建指定填充速率、容量大小和每次填充的令牌数的令牌桶 func NewBucketWithQuantum(fillInterval time.Duration, capacity, quantum int64) *Bucket // 创建填充速度为指定速率和容量大小的令牌桶 // NewBucketWithRate(0.1, 200) 表示每秒填充20个令牌 func NewBucketWithRate(rate float64, capacity int64) *Bucket取出令牌的方法如下 // 取token非阻塞 func (tb *Bucket) Take(count int64) time.Duration func (tb *Bucket) TakeAvailable(count int64) int64// 最多等maxWait时间取token func (tb *Bucket) TakeMaxDuration(count int64, maxWait time.Duration) (time.Duration, bool)// 取token阻塞 func (tb *Bucket) Wait(count int64) func (tb *Bucket) WaitMaxDuration(count int64, maxWait time.Duration) bool虽说是令牌桶但是我们没有必要真的去生成令牌放到桶里我们只需要每次来取令牌的时候计算一下当前是否有足够的令牌就可以了具体的计算方式可以总结为下面的公式 当前令牌数 上一次剩余的令牌数 (本次取令牌的时刻-上一次取令牌的时刻)/放置令牌的时间间隔 * 每次放置的令牌数github.com/juju/ratelimit这个库中关于令牌数计算的源代码如下 func (tb *Bucket) currentTick(now time.Time) int64 {return int64(now.Sub(tb.startTime) / tb.fillInterval) }func (tb *Bucket) adjustavailableTokens(tick int64) {if tb.availableTokens tb.capacity {return}tb.availableTokens (tick - tb.latestTick) * tb.quantumif tb.availableTokens tb.capacity {tb.availableTokens tb.capacity}tb.latestTick tickreturn }获取令牌的TakeAvailable()函数关键部分的源代码如下 func (tb *Bucket) takeAvailable(now time.Time, count int64) int64 {if count 0 {return 0}tb.adjustavailableTokens(tb.currentTick(now))if tb.availableTokens 0 {return 0}if count tb.availableTokens {count tb.availableTokens}tb.availableTokens - countreturn count }大家从代码中也可以看到其实令牌桶的实现并没有很复杂。 gin框架中使用限流中间件 在gin框架构建的项目中我们可以将限流组件定义成中间件。 这里使用令牌桶作为限流策略编写一个限流中间件如下 func RateLimitMiddleware(fillInterval time.Duration, cap int64) func(c *gin.Context) {bucket : ratelimit.NewBucket(fillInterval, cap)return func(c *gin.Context) {// 如果取不到令牌就中断本次请求返回 rate limit...if bucket.TakeAvailable(1) 1 {c.String(http.StatusOK, rate limit...)c.Abort()return}c.Next()} }对于该限流中间件的注册位置我们可以按照不同的限流策略将其注册到不同的位置例如 如果要对全站限流就可以注册成全局的中间件。如果是某一组路由需要限流那么就只需将该限流中间件注册到对应的路由组即可。
http://www.zqtcl.cn/news/149221/

相关文章:

  • 做a的网站有哪些在国外做网站推广
  • 做外贸网站设计上需要注意什么python做音乐网站
  • 英语门户网站织梦源码wordpress 推荐插件
  • 学做衣服网站有哪些网站建设算入会计分录
  • 京东网站开发技术织梦网站如何做404
  • 论坛类网站开发屏蔽wordpress缩略图
  • 南宁市两学一做网站logo设计网站官网
  • 中国建设工程造价管理协会网站查询网站开发者的设计构想
  • 华强北网站建设设计素材网站p开头的
  • 怎样让网站快速收录利用数据库修改wordpress密码
  • 网站建设群发广告词做网站首页多少钱
  • 黑彩网站建设中企动力 网站价格
  • 上海营销型网站报价深圳企业网站制作设计
  • 网站清理通知北京电商购物网站
  • 新开传奇网站180合击创建一个个人网站需要多少钱
  • 郑州建网站哪家好深圳企业网站制作公司介绍
  • 企业网站百度收录桂林网站建设价格
  • 砀山做网站的公司wordpress微视频主题
  • 免费的企业网站cms注册网站后邮箱收到邮件
  • 网站推广排名教程怀化职院网站
  • 房产门户网站模板新手做电商怎么起步
  • 成都网站建设科技公沈阳网站建设技术公司排名
  • 自建商城网站上海有哪些网络公司
  • 朋友 合同 网站制作手机网站建设服务商
  • 链接分析属于网站开发棋牌软件开发定制
  • top域名的网站搭建网站步骤
  • 个人网站建设背景和目的海南省网站
  • 山西成宁做的网站义乌网站建设优化排名
  • 东莞网站建设公司辉煌大厦阿里云服务器官方网站
  • 域名注册网站制作自己建网站需要钱吗