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
Golang限制函数调用次数的更多相关文章
- Java 中的 int 与 Integer 用于 List<Integer> 时,以及通过打印变量检測程序执行和函数调用次数计数
总结一下近期做的东西中遇到的问题 1. Java 中的 int 与 Integer 用于 List<Integer> 时 两者之间的关系都是非常清楚的.int 是基本数据类型,存储的是值 ...
- golang mcall
// func mcall(fn func(*g)) // Switch to m->g0's stack, call fn(g). // Fn must never return. It sh ...
- 一个能让你了解所有函数调用顺序的Android库
http://mobile.51cto.com/android-536059.htm 原理 本库其实并没有什么黑科技,本库也没有java代码,核心就是2个build.gradle中的task.首先,原 ...
- How Javascript works (Javascript工作原理) (一) 引擎,运行时,函数调用栈
个人总结:该系列文章对JS底层的工作原理进行了介绍. 这篇文章讲了 运行时:js其实是和AJAX.DOM.Settimeout等WebAPI独立分离开的 调用栈:JavaScript的堆内存管理 和 ...
- Prometheus Metrics 设计的最佳实践和应用实例,看这篇够了!
Prometheus 是一个开源的监控解决方案,部署简单易使用,难点在于如何设计符合特定需求的 Metrics 去全面高效地反映系统实时状态,以助力故障问题的发现与定位.本文即基于最佳实践的 Metr ...
- 怎么调试lua性能
怎么调试lua性能 我们的游戏使用的是Cocos2dx-lua 3.9的项目,最近发现我们的游戏.运行比较缓慢.想做一次性能优化了.其实主要分为GPU.CPU的分别优化.GPU部分的优化.网上有很多优 ...
- JS学习:第二周——NO.1回调函数
[回调函数] 定义:把一个函数的定义阶段,作为参数,传给另一个函数: 回调函数调用次数,取决于条件: 回调函数可以传参: 回调函数可以给变this指向,默认是window: 回调函数没有返回值,for ...
- 跟vczh看实例学编译原理——一:Tinymoe的设计哲学
自从<序>胡扯了快一个月之后,终于迎来了正片.之所以系列文章叫<看实例学编译原理>,是因为整个系列会通过带大家一步一步实现Tinymoe的过程,来介绍编译原理的一些知识点. 但 ...
- SQL SERVER中用户定义标量函数(scalar user defined function)的性能问题
用户定义函数(UDF)分类 SQL SERVER中的用户定义函数(User Defined Functions 简称UDF)分为标量函数(Scalar-Valued Function)和表值函数(T ...
随机推荐
- 动态类型转换dynamic_cast
C++Primer第十九章的动态类型转换部分讲的不是很清楚,于是自己查cpp的官方手册总结一下. dynamic_cast < new-type > ( expression ) 动态类型 ...
- Qt事件与常用事件处理、过滤
转载: https://blog.csdn.net/apollon_krj/article/category/6939539 https://blog.csdn.net/qq_41072190/art ...
- k8s创建资源的两种方式及DaemonSet应用(5)
一.创建方式分类 Kubernetes 支持两种方式创建资源: (1)用 kubectl 命令直接创建,比如: kubectl run httpd-app --image=reg.yunwei.com ...
- Spark SQL 之 RDD、DataFrame 和 Dataset 如何选择
引言 Apache Spark 2.2 以及以上版本提供的三种 API - RDD.DataFrame 和 Dataset,它们都可以实现很多相同的数据处理,它们之间的性能差异如何,在什么情况下该选用 ...
- CCproxy 代理上网
相信有些同学在工作过程中遇到过公司内网环境无法上网的情况,下面给大家介绍一下CCproxy代理上网的配置 场景:linux虚拟机通过CCproxy代理访问外网 环境:只能访问内网的linux环境,可以 ...
- python3 使用random函数批量产生注册邮箱
'''你是一个高级测试工程师,现在要做性能测试,需要你写一个函数,批量生成一些注册使用的账号. 1.产生的账号是以@163.com结尾,长度由用户输,产生多少条也由用户输入,2.用户名不能重复,用户名 ...
- Angular环境搭建及简单体验
一.安装开发环境 npm install -g typescript npm install -g @angular/cli 二.创建hello-world项目 创建项目 ng new angular ...
- Spring的三种注入
在学习Spring的过程中,其中一个很重要的就是依赖注入DI,在此总结一下 注入方式有三种: 一.构造器注入 二.Set方式注入(重点) 三.扩展方式注入 构造器注入: a.默认使用无参构造函数创建对 ...
- 行者APP适配国外环境问题解决
(本文1151字,阅读约5分钟) 玩骑行的同伴都知道,长途骑行,第一需要好的硬件,如大腿发动机.车子.装备等:二是需要好的软件,如意志.有氧能力.骑行app等. 到雅加达后,才发现在国内用了几年的黑鸟 ...
- 在Docker中安装MongoDB
在Docker中安装MongoDB docker run -p 27017:27017 -v /data/mongodb:/data/db --name mongodb -d mongo --auth ...