go语言漏桶算法思路简单实现

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)
	}
}

  

posted @ 2019-10-24 22:34  ALXPS  阅读(817)  评论(0编辑  收藏  举报