Go 语言 服务限流算法 令牌桶与漏桶在 Go 中的实现

Go阿木 发布于 22 天前 3 次阅读


Go 语言服务限流算法:令牌桶与漏桶实现

在分布式系统中,为了防止系统过载,保护系统稳定运行,限流算法是必不可少的。限流算法可以有效地控制请求的速率,防止恶意攻击和异常流量对系统造成影响。本文将围绕Go语言,详细介绍两种常见的限流算法:令牌桶和漏桶,并给出相应的实现代码。

令牌桶算法

令牌桶算法是一种常见的限流算法,它允许一定速率的请求通过,同时可以应对突发流量。令牌桶算法的核心思想是维护一个桶,桶中存放一定数量的令牌,每个请求需要消耗一个令牌才能通过。

令牌桶算法原理

1. 初始化一个桶,桶中存放一定数量的令牌。

2. 以固定速率向桶中添加令牌。

3. 当请求到来时,检查桶中是否有令牌:

- 如果有令牌,则消耗一个令牌,请求通过。

- 如果没有令牌,则请求被拒绝。

Go语言实现

go

package main

import (


"fmt"


"time"


)

type TokenBucket struct {


rate float64 // 添加令牌的速率


capcity int // 桶的容量


tokens int // 当前令牌数量


}

func NewTokenBucket(rate float64, capcity int) TokenBucket {


return &TokenBucket{


rate: rate,


capcity: capcity,


tokens: capcity,


}


}

func (tb TokenBucket) Allow() bool {


if tb.tokens > 0 {


tb.tokens--


return true


}


return false


}

func (tb TokenBucket) Refill() {


for {


tb.tokens++


if tb.tokens >= tb.capcity {


break


}


time.Sleep(time.Second / time.Duration(tb.rate))


}


}

func main() {


tokenBucket := NewTokenBucket(1, 5)


go tokenBucket.Refill()

for i := 0; i < 10; i++ {


if tokenBucket.Allow() {


fmt.Println("Request", i, "allowed")


} else {


fmt.Println("Request", i, "denied")


}


time.Sleep(time.Second)


}


}


漏桶算法

漏桶算法是一种允许一定速率的请求通过,同时可以应对突发流量的限流算法。漏桶算法的核心思想是维护一个桶,桶中存放一定数量的水,水以固定速率流出。

漏桶算法原理

1. 初始化一个桶,桶中存放一定数量的水。

2. 以固定速率从桶中流出水。

3. 当请求到来时,检查桶中是否有水:

- 如果有水,则流出一定量的水,请求通过。

- 如果没有水,则请求被拒绝。

Go语言实现

go

package main

import (


"fmt"


"time"


)

type Bucket struct {


rate float64 // 流出水的速率


capcity int // 桶的容量


water int // 当前水量


}

func NewBucket(rate float64, capcity int) Bucket {


return &Bucket{


rate: rate,


capcity: capcity,


water: capcity,


}


}

func (b Bucket) Allow() bool {


if b.water > 0 {


b.water--


return true


}


return false


}

func (b Bucket) Refill() {


for {


b.water++


if b.water >= b.capcity {


break


}


time.Sleep(time.Second / time.Duration(b.rate))


}


}

func main() {


bucket := NewBucket(1, 5)


go bucket.Refill()

for i := 0; i < 10; i++ {


if bucket.Allow() {


fmt.Println("Request", i, "allowed")


} else {


fmt.Println("Request", i, "denied")


}


time.Sleep(time.Second)


}


}


总结

本文介绍了两种常见的限流算法:令牌桶和漏桶,并给出了Go语言的实现代码。在实际应用中,可以根据具体需求选择合适的限流算法,以保护系统稳定运行。