package main import ( "fmt" "time" ) // 桶 type LeakBucket struct { capacity int // 容量,固定时间语序访问次数 interval time.Duration // 允许访问的时间间隔 dropsNum int // 固定时间访问了多少次 lastAccessTime time.Time // 最近一次的访问时间 } func (b *LeakBucket) accessControl() bool { now := time.Now() pastTime := now.Sub(b.lastAccessTime) // 过去这段时间pastTime可以允许多少访问 leaks := int(float64(pastTime) / float64(b.interval)) if leaks > 0 { // 说明这段时间可以有leaks可以访问,但没有用户访问 // 所以放宽访问,下一段访问限制减少一定leaks次限制,通过这种机制达到平滑控制流量 if b.dropsNum <= leaks { b.dropsNum = 0 } else { b.dropsNum -= leaks } // 更新访问时间 b.lastAccessTime = now } if b.dropsNum < b.capacity { // 在允许访问之内 b.dropsNum ++ return true } else { return false } } func main() { bucket := &LeakBucket{ capacity: 10, interval: time.Second, } for i := 0; i < 12; i++ { allowed := bucket.accessControl() fmt.Println("i",i) fmt.Println("i",allowed) time.Sleep(time.Millisecond * 500) } time.Sleep(time.Second*3) // 模拟3秒中时间内没有访问 fmt.Println("空档期走完") for j := 0; j < 20; j++ { fmt.Println("BEFORE",bucket.dropsNum) allowed := bucket.accessControl() fmt.Println("AFTER",bucket.dropsNum) fmt.Println("j", j) fmt.Println("j",allowed) time.Sleep(time.Millisecond * 500) } }