【GO】简单的令牌桶限速实现

通过chan来实现一个简单的令牌桶限速,初始化一个chan之后,一个gorouting负责按设定的速率往里面放令牌,调用的时候取令牌,取到则可以继续执行,否则则表示被限流。
简单的代码实现如下:

package main

import (
	"fmt"
	"net/http"
	"time"
)

var lim *Limit

// Limit 限速器
type Limit struct {
	ch chan struct{}
}

// NewLimiter 生成一个限速器并开始往里面放令牌
// rate: 速率,单位次每秒
// cap: 令牌桶的容量
func NewLimiter(rate, cap int) *Limit {
	limit := Limit{
		ch: make(chan struct{}, cap),
	}
	go func() {
		ticker := time.NewTicker(time.Duration(1000000/rate) * time.Microsecond)
		for {
			select {
			case <-ticker.C:
				limit.ch <- struct{}{}
			}
		}
	}()
	return &limit
}

// Allow 判断是否获取到令牌
func (lim *Limit) Allow() bool {
	select {
	case <-lim.ch:
		return true
	default:
		return false
	}
}

func hello(w http.ResponseWriter, req *http.Request) {
	if lim.Allow() {
		w.WriteHeader(200)
		fmt.Fprintln(w, "hello")
	} else {
		w.WriteHeader(403)
		fmt.Fprintln(w, "deny")
	}

}

func main() {
	lim = NewLimiter(100, 100)
	http.HandleFunc("/", hello)
	http.ListenAndServe(":8888", nil)
}

按照速率100/s,桶容量100来启动服务。
启动服务之后,使用go-wrt来进行测试
go-wrk -t=8 -c=100 -n=10000 “http://127.0.0.1:8888/”
结果如下:

==========================BENCHMARK==========================
URL:                            http://127.0.0.1:8888/

Used Connections:               100
Used Threads:                   8
Total number of calls:          10000

===========================TIMINGS===========================
Total time passed:              1.16s
Avg time per request:           11.44ms
Requests per second:            8585.02
Median time per request:        8.47ms
99th percentile time:           288.15ms
Slowest time for request:       298.00ms

=============================DATA=============================
Total response body sizes:              50217
Avg response body per request:          5.02 Byte
Transfer rate per second:               43111.38 Byte/s (0.04 MByte/s)
==========================RESPONSES==========================
20X Responses:          217     (2.17%)
30X Responses:          0       (0.00%)
40X Responses:          9783    (97.83%)
50X Responses:          0       (0.00%)
Errors:                 0       (0.00%)

因为是先启动之后,然后再启动测试脚本的。从结果来看,初始100个令牌满了,执行时间1.16s,往里面又放了116个,总计应该是216个未被限流。结果是217,符合预期。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值