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 ...
随机推荐
- Shell 脚本重启项目
每次发打包好项目后都需要手动重启项目,写个Shell脚本一键重启项目 Shell 脚本 #!/bin/bash while getopts "n:p:" arg do case $ ...
- goland mod模式下不从vendor文件夹查找依赖
goland使用vendor作为获取依赖源 软件版本: system:windows10 1709 terminal: wsl ubuntu1804 goland:201903 goland 打开项目 ...
- [刷题] 46 Permutations
要求 整型数组,每个元素不相同,返回元素所有排列的可能 示例 [1,2,3] [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ] 思路 树 ...
- 删除所有空白列 cat yum.log | awk '{$1=$2=$3=$4=null;print $0}'>>yum.log1 sed ‘s/[ \t]*$//g' 删除所有空格 sed -i s/[[:space:]]//g yum.log
2.删除行末空格 代码如下: 删除所有空白列 cat yum.log | awk '{$1=$2=$3=$4=null;print $0}'>>yum.log1 sed 's/[ \t]* ...
- 【Git】git clone报错 git fatal: Unable to find remote helper for 'https'
[参考资料] https://stackoverflow.com/questions/8329485/unable-to-find-remote-helper-for-https-during-git ...
- 基于端口划分vlan
基于端口划分vlan 拓扑图 PC ip 配置 PC 5:192.168.1.5 PC 6:192.168.1.6 PC 7:192.168.1.7 PC 8: 192.168.1.8 交换机配置 创 ...
- jmeter 通过CSV Data Set Config控件参数化
CSV Data Set Config控件配置如下: 被导入的.csv 文件内容如下 用excel打开如下 设置中url2对应:cn.toursforfun.com 和 www.163.com url ...
- 分布式存储ceph---部署ceph(2)
一.部署准备 准备5台机器(linux系统为centos7.6版本),当然也可以至少3台机器并充当部署节点和客户端,可以与ceph节点共用: 1台部署节点(配一块硬盘,运行ceph-depoly) 3 ...
- rpm命令的简介-(转自jb51.net )
在Linux操作系统中,有一个系统软件包,它的功能类似于Windows里面的"添加/删除程序",但是功能又比"添加/删除程序"强很多,它就是Red Hat Pa ...
- 也谈如何写一个Webserver(三)
在上一篇里,我介绍了如何应用socket和epoll来组织和管理从客户端(如,浏览器)传入的连接,通过设置非阻塞连接让Webserver有更好的性能. 下面,我介绍一下在我写的Webserver Ma ...