前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >流量暴增如何应对?漏桶限流算法,让你轻松应对流量高峰!揭晓标准代码,超乎想象的稳定、简单!”

流量暴增如何应对?漏桶限流算法,让你轻松应对流量高峰!揭晓标准代码,超乎想象的稳定、简单!”

作者头像
程序视点
发布2024-06-07 14:48:44
790
发布2024-06-07 14:48:44
举报
文章被收录于专栏:程序小小事程序小小事

前言

前文,我们分享了限流算法中的滑动窗口算法及其实践。尽管滑动窗口算法可以提供一定的限流效果,但它仍然受限于窗口的大小和时间间隔

在某些情况下,突发流量可能会导致窗口内的请求数超过限制。今天分享的漏桶限流算法,就能很好的改进这个问题。

漏桶限流

算法介绍

漏桶限流算法就是为了更好地平滑请求的流量,改进滑动窗口算法的弊端。算法的原理很简单:它维护一个固定容量的漏桶,请求以不定的速率流入漏桶,而漏桶以固定的速率流出。如果请求到达时,漏桶已满,则会触发拒绝策略。

可以从生产者-消费者模式去理解这个算法,请求充当生产者,每个请求就像一滴水,当请求到达时,它被放入一个队列(漏桶)中。而漏桶则充当消费者,以固定的速率从队列中消费请求,就像从桶底的孔洞中不断漏出水滴。

消费的速率等于限流阈值,例如每秒处理2个请求,即500毫秒消费一个请求。漏桶的容量就像队列的容量,当请求堆积超过指定容量时,会触发拒绝策略,即新到达的请求将被丢弃或延迟处理。算法的实现如下:

  1. 漏桶容量:确定一个固定的漏桶容量,表示漏桶可以存储的最大请求数。
  2. 漏桶速率:确定一个固定的漏桶速率,表示漏桶每秒可以处理的请求数。
  3. 请求处理:当请求到达时,生产者将请求放入漏桶中。
  4. 漏桶流出:漏桶以固定的速率从漏桶中消费请求,并处理这些请求。如果漏桶中有请求,则处理一个请求;如果漏桶为空,则不处理请求。
  5. 请求丢弃或延迟:如果漏桶已满,即漏桶中的请求数达到了容量上限,新到达的请求将被丢弃或延迟处理。

代码实现

代码语言:javascript
复制
package main

import (
   "fmt"
   "time"
)

type LeakyBucket struct {
   rate       float64 // 漏桶速率,单位请求数/秒
   capacity   int     // 漏桶容量,最多可存储请求数
   water      int     // 当前水量,表示当前漏桶中的请求数
   lastLeakMs int64   // 上次漏水的时间戳,单位秒
}

func NewLeakyBucket(rate float64, capacity int) *LeakyBucket {
   return &LeakyBucket{
      rate:       rate,
      capacity:   capacity,
      water:      0,
      lastLeakMs: time.Now().Unix(),
   }
}

func (lb *LeakyBucket) Allow() bool {
   now := time.Now().Unix()
   elapsed := now - lb.lastLeakMs

   // 漏水,根据时间间隔计算漏掉的水量
   leakAmount := int(float64(elapsed) / 1000 * lb.rate)
   if leakAmount > 0 {
      if leakAmount > lb.water {
         lb.water = 0
      } else {
         lb.water -= leakAmount
      }
   }

   // 判断当前水量是否超过容量
   if lb.water > lb.capacity {
      lb.water-- // 如果超过容量,减去刚刚增加的水量
      return false
   }

   // 增加水量
   lb.water++

   lb.lastLeakMs = now
   return true
}

func main() {
   // 创建一个漏桶,速率为每秒处理3个请求,容量为4个请求
   leakyBucket := NewLeakyBucket(3, 4)

   // 模拟请求
   for i := 1; i <= 15; i++ {
      now := time.Now().Format("15:04:05")
      if leakyBucket.Allow() {
         fmt.Printf(now+"  第 %d 个请求通过\n", i)
      } else {
         fmt.Printf(now+"  第 %d 个请求被限流\n", i)
      }
      time.Sleep(200 * time.Millisecond) // 模拟请求间隔
   }
}

执行结果:

优缺点

优点

  1. 平滑流量:漏桶算法可以平滑突发流量,使得输出流量变得更加平稳,避免了流量的突然增大对系统的冲击。
  2. 简单易实现:漏桶算法的原理简单,实现起来也相对容易。
  3. 有效防止过载:通过控制流出的流量,漏桶算法可以有效地防止系统过载。

缺点

  1. 对突发流量的处理不够灵活:虽然漏桶算法可以平滑突发流量,但是在某些情况下,我们可能希望能够快速处理突发流量。在这种情况下,漏桶算法可能就不够灵活了。
  2. 无法动态调整流量:漏桶算法的流出速率是固定的,无法根据系统的实际情况动态调整。
  3. 可能会导致流量浪费:如果输入流量小于漏桶的流出速率,那么漏桶的流出速率就会被浪费。
  4. 如果输入流量持续大于漏桶的流出速率,那么漏桶会一直满,新的请求会被丢弃,可能会导致服务质量下降。

利弊都给大家分享了!怎么更进一步呢?下期再和你分享一个最常见的思路!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-05-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序视点 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档