令牌桶算法的基本過程如下:
- 假如用戶配置的平均發(fā)送速率為r,則每隔1/r秒一個令牌被加入到桶中;
- 假設桶最多可以存發(fā)b個令牌。如果令牌到達時令牌桶已經(jīng)滿了,那么這個令牌會被丟棄;
- 當一個n個字節(jié)的數(shù)據(jù)包到達時,就從令牌桶中刪除n個令牌,并且數(shù)據(jù)包被發(fā)送到網(wǎng)絡;
package main
import (
"fmt"
"sync"
"time"
)
type Bucket struct {
cap int //容量
ch chan bool
timer *time.Ticker //定時填充token
mu sync.Mutex
}
func NewBucket(cap int, interval time.Duration) *Bucket {
bucket := &Bucket{
cap: cap,
ch: make(chan bool, cap),
timer: time.NewTicker(interval),
}
go bucket.startTicker()
return bucket
}
func (bucket *Bucket) startTicker() {
for i := 0; i < bucket.cap; i++ {
bucket.ch <- true
}
for {
select {
case <-bucket.timer.C:
for i := len(bucket.ch); i < bucket.cap; i++ {
bucket.Add()
}
}
}
}
func (bucket *Bucket) Add() {
bucket.mu.Lock()
defer bucket.mu.Unlock()
if len(bucket.ch) < bucket.cap {
bucket.ch <- true
}
}
func (bucket *Bucket) Get() bool {
select {
case <-bucket.ch:
return true
default:
return false
}
}
func main() {
bucket := NewBucket(5, time.Second)
for i := 0; i < 1000; i++ {
time.Sleep(time.Millisecond * 100)
go DoFunc(bucket, i)
}
for {
}
}
func DoFunc(bucket *Bucket, index int) {
if bucket.Get() {
fmt.Printf("######### success : %d \n", index)
bucket.Add() // 每次請求成功后執(zhí)行Add是否合理???每一時刻最多可有cap個token可用
} else {
fmt.Printf("######### failed : %d \n", index)
}
}
最后編輯于 :
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。