zoukankan      html  css  js  c++  java
  • Golang限制函数调用次数

    Golang限制函数调用次数

    项目环境

    • ubuntu+go1.14

    需求描述

    • 限制某个函数5秒内只能调用一次,5秒内的其他调用抛弃

    工具包使用

    这里用到了官方限流器/time/rate

    该限流器是基于Token Bucket(令牌桶)实现的。

    简单来说,令牌桶就是一个固定大小的桶,系统会以恒定速率向桶中放Token,桶满则暂时不放。
    而用户则从桶中取Token,如果有剩余Token就可以一直取。如果没有剩余Token,则需要等到系统中被放置了Token才行。

    方法简介:

    NewLimiter

    func NewLimiter(r Limit, b int) *Limiter
    

    这里有两个参数:

    • 第一个参数是r Limit。代表每秒可以向Token桶中产生多少token。Limit实际上是float64的别名。

    • 第二个参数是b int。b代表Token桶的容量大小。

    除了直接指定每秒产生的Token个数外,还可以用Every方法来指定向Token桶中放置Token的间隔

    例如我的需求是5秒只能访问一次,那我就5秒放一个Token,桶中最多保存1个:

    var r = rate.Every( 5 * time.Second)
    var limiter = NewLimiter(limit, 1);
    

    Wait/WaitN

    func (lim *Limiter) Wait(ctx context.Context) (err error)
    func (lim *Limiter) WaitN(ctx context.Context, n int) (err error)
    

    Wait是WaitN(ctx,1)的简写。

    当使用Wait方法消费Token时,如果此时桶内Token数组不足(小于N),那么Wait方法将会阻塞一段时间,直至Token满足条件。如果充足则直接返回。

    Wait方法有一个context参数,我们可以设置context的Deadline或者Timeout,来决定此次Wait的最长时间。

    Allow/AllowN

    func (lim *Limiter) Allow() bool
    func (lim *Limiter) AllowN(now time.Time, n int) bool
    

    Allow是AllowN(time.Now(),1)的简写。

    AllowN方法表示,截止到某一时刻,目前桶中数目是否至少为n个,满足则返回true,同时从桶中消费n个token。
    反之返回不消费Token,false。

    如果你需要在事件超出频率的时候丢弃或跳过事件,就使用AllowN,否则使用Reserve或Wait.

    结合我的需求,没有Token就抛弃,我用这个Allow

    if !limit.Allow() {
    	fmt.Println(" has no token")
    	return
    }else{
    	fmt.Println(" has  token")
    }
    

    Reserve/ReserveN

    func (lim *Limiter) Reserve() *Reservation
    func (lim *Limiter) ReserveN(now time.Time, n int) *Reservation
    

    Reserve是ReserveN(time.Now(), 1)的简写。

    ReserveN 返回对象Reservation

    该对象的Delay()方法返回了需要等待的时间,必须等到等待时间之后,才能进行接下来的工作。

    如果不想等待,可以调用Cancel()方法,该方法会将Token归还。

    使用示例

    r := lim.ReserveN(time.Now(), 1)
    if !r.OK() {
      // 如果ReserveN 传入的n大于令牌池的容量b,那么返回false.
      return
    }
    time.Sleep(r.Delay())
    Act() //处理逻辑
    

    实现Demo

    package main
    
    import (
    	"fmt"
    	"golang.org/x/time/rate"
    	"time"
    )
    func main() {
    	// 模拟每500毫秒调用一次t函数
    	for{
    		t()
    		time.Sleep(time.Millisecond* 500)
    	}
    }
    
    var r = rate.Every( 5 * time.Second)
    var limit = rate.NewLimiter(r, 1)
    
    func t() {
    	if !limit.Allow() {
    		fmt.Println(" has no token")
    		return
    	}else{
    		fmt.Println(" has  token")
    	}
    }
    

    打印

    root@ubuntu14:/home/kingram/sourceCode/test# go build t4.go
    root@ubuntu14:/home/kingram/sourceCode/test# ./t4
     has  token
     has no token
     has no token
     has no token
     has no token
     has no token
     has no token
     has no token
     has no token
     has no token
     has  token
     has no token
     has no token
     has no token
     has no token
     has no token
     has no token
     has no token
     has no token
     has no token
     has  token
    
  • 相关阅读:
    Atitit 引流矩阵与矩阵引流 推广方法 attilax总结
    Atitit 怎么阅读一本书 消化 分析 检索 attilax总结 1. 读书的本质 是数据的处理,大量的数据,处理能力有限的大脑 2 2. ETL数据清洗转换 摘要,缩小数据规模 2 2.1
    Atitit 为什么要读书,读书的好处是什么 attilax总结
    Atititi. naming spec 联系人命名与remark备注指南规范v5 r99.docx
    Atitit 安全规范 指南 常见五种意外防止规范 attilax总结
    数据安全 密码学原理与概论
    Atitit 理财之道分期与利率的比较列表 attilax总结
    Atitit 完整知识体系表 attilax总结 要读哪些书
    Atitit 为什么互联网机会这么大
    Atitit 建立新组织集团模型的框架基本制度与一些原则
  • 原文地址:https://www.cnblogs.com/Kingram/p/13445666.html
Copyright © 2011-2022 走看看