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

Golang限制函数调用次数的更多相关文章

  1. Java 中的 int 与 Integer 用于 List<Integer> 时,以及通过打印变量检測程序执行和函数调用次数计数

    总结一下近期做的东西中遇到的问题 1. Java 中的 int 与 Integer 用于 List<Integer>  时 两者之间的关系都是非常清楚的.int 是基本数据类型,存储的是值 ...

  2. golang mcall

    // func mcall(fn func(*g)) // Switch to m->g0's stack, call fn(g). // Fn must never return. It sh ...

  3. 一个能让你了解所有函数调用顺序的Android库

    http://mobile.51cto.com/android-536059.htm 原理 本库其实并没有什么黑科技,本库也没有java代码,核心就是2个build.gradle中的task.首先,原 ...

  4. How Javascript works (Javascript工作原理) (一) 引擎,运行时,函数调用栈

    个人总结:该系列文章对JS底层的工作原理进行了介绍. 这篇文章讲了 运行时:js其实是和AJAX.DOM.Settimeout等WebAPI独立分离开的 调用栈:JavaScript的堆内存管理 和 ...

  5. Prometheus Metrics 设计的最佳实践和应用实例,看这篇够了!

    Prometheus 是一个开源的监控解决方案,部署简单易使用,难点在于如何设计符合特定需求的 Metrics 去全面高效地反映系统实时状态,以助力故障问题的发现与定位.本文即基于最佳实践的 Metr ...

  6. 怎么调试lua性能

    怎么调试lua性能 我们的游戏使用的是Cocos2dx-lua 3.9的项目,最近发现我们的游戏.运行比较缓慢.想做一次性能优化了.其实主要分为GPU.CPU的分别优化.GPU部分的优化.网上有很多优 ...

  7. JS学习:第二周——NO.1回调函数

    [回调函数] 定义:把一个函数的定义阶段,作为参数,传给另一个函数: 回调函数调用次数,取决于条件: 回调函数可以传参: 回调函数可以给变this指向,默认是window: 回调函数没有返回值,for ...

  8. 跟vczh看实例学编译原理——一:Tinymoe的设计哲学

    自从<序>胡扯了快一个月之后,终于迎来了正片.之所以系列文章叫<看实例学编译原理>,是因为整个系列会通过带大家一步一步实现Tinymoe的过程,来介绍编译原理的一些知识点. 但 ...

  9. SQL SERVER中用户定义标量函数(scalar user defined function)的性能问题

    用户定义函数(UDF)分类  SQL SERVER中的用户定义函数(User Defined Functions 简称UDF)分为标量函数(Scalar-Valued Function)和表值函数(T ...

随机推荐

  1. 一文读懂 SuperEdge 云边隧道

    作者 李腾飞,腾讯容器技术研发工程师,腾讯云TKE后台研发,SuperEdge核心开发成员. 杜杨浩,腾讯云高级工程师,热衷于开源.容器和Kubernetes.目前主要从事镜像仓库,Kubernete ...

  2. IP包头部格式解析

    IPv4首部一般是20字节长.在以太网帧中,IPv4包首部紧跟着以太网帧首部,同时以太网帧首部中的协议类型值设置为080016. IPv4提供不同,大部分是很少用的选项,使得IPv4包首部最长可扩展到 ...

  3. re_path 的 ?P<>

  4. 如何使用GoLand debug

    debug 常用操作 /* 如何使用 goland debug goroutine */ package main import ( "fmt" "runtime&quo ...

  5. Spring AOP 用法浅谈(Day_18)

    当你这一天没有在进步,那你就是在退步! [简述] Aspect Oriented Programming :面向切面编程 所谓面向切面编程,是一种通过预编译和运行期动态代理的方式实现在不修改源代码的情 ...

  6. HarmonyOS去除页面顶部title的方式

    在config.json文件中module节点中添加如下代码 "metaData":{ "customizeData":[ { "name" ...

  7. .NET平台系列13 .NET5 统一平台

    系列目录     [已更新最新开发文章,点击查看详细] 时机决定一切,对于 .NET5 也是如此.实际上微软.NET团队在开始开发 .NET Core 时,对 .NET Framework 的全面重写 ...

  8. IDEA 最实用快捷键【MAC版本】

    目录 option + F7 Ctrl + B / Ctrl +鼠标左键(一键两用,可以无限循环的跳过来跳过去,我跳过去了,我又跳回去了) command + E (这个快捷键很有用,为什么我老是用不 ...

  9. Go语言网络通信---连续通信的UDP编程

    Server: package main import ( "fmt" "net" ) func main() { //创建udp地址 udpAddr, _ : ...

  10. 2021.5.22 noip模拟1

    这场考试考得很烂 连暴力都没打好 只拿了25分,,,,,,,,好好总结 T1序列 A. 序列 题目描述 HZ每周一都要举行升旗仪式,国旗班会站成一整列整齐的向前行进. 郭神作为摄像师想要选取其中一段照 ...