首页 > 其他分享 >golang实现限制每秒多少次的限频操作

golang实现限制每秒多少次的限频操作

时间:2022-11-22 11:35:09浏览次数:39  
标签:限频 fmt lastExecTime golang func time runtime 每秒


前言

一些函数的执行可能会限制频率,比如某个api接口要求每秒最大请求30次。下面记录了自己写的限频和官方的限频

代码

// 加锁限频,输出次数大概率小于最大值
func ExecLimit(lastExecTime *time.Time, l *sync.RWMutex ,maxTimes int, perDuration time.Duration, f func()) {
l.Lock()
defer l.Unlock()
// per times cost time(s)
SecondsPerTimes := float64(perDuration) / float64(time.Second) / float64(maxTimes)

now := time.Now()
interval := now.Sub(*lastExecTime).Seconds()
if interval < SecondsPerTimes {
time.Sleep(time.Duration(int64((SecondsPerTimes-interval)*1000000000)) * time.Nanosecond)
}
f()
*lastExecTime = time.Now()
}

// 官方的,需要引用 "golang.org/x/time/rate"
// 基本上可以达到满值,比自己写的更优
func ExecLimit2(l *rate.Limiter, f func()) {
go func() {
l.Wait(context.Background())
f()
}()
}

使用

func TestExecLimit(t *testing.T) {
runtime.GOMAXPROCS(runtime.NumCPU())
go func() {
var lastExecTime time.Time
var l sync.RWMutex
for {
ExecLimit(&lastExecTime, &l, 10, time.Second, func() {
fmt.Println("do")
})
}
}()

select {
case <-time.After(1 * time.Second):
fmt.Println("1秒到时")
}
}

func TestExecLimit2(t *testing.T) {
runtime.GOMAXPROCS(runtime.NumCPU())

l := rate.NewLimiter(1, 30)

go func() {
for {
ExecLimit2(l, func() {
fmt.Println("do")
})
}
}()

select {
case <-time.After(1 * time.Second):
fmt.Println("1秒到时")
}
}

输出:

一秒内输出了<=10次 "do"

如何在多节点服务中限制频

上述使用,定义在某个服务节点的全局变量lastExecTime仅仅会对该服务的函数f()操作限频,如果在负载均衡后,多个相同服务的节点,对第三方的接口累计限频,比如三个服务共同拉取第三方接口,合计限频为30次/s.
则,必须将lastExecTime的获取,从redis等共享中间件中获取,而不应该从任何一个单点服务获取。


标签:限频,fmt,lastExecTime,golang,func,time,runtime,每秒
From: https://blog.51cto.com/u_11553781/5877252

相关文章

  • Golang学习日志 ━━ 理解依赖包的管理(mod/非mod)和加载方式(项目路径、相对路径、绝对
    go有很多种方法调用依赖包,mod又加入了对包的版本管理。方式太多不免有令人迷惑和混乱的地方,希望本文能帮助大家了解目前使用规则一、mod/非mod管理方式go提供了两种项目......
  • CentOS6.4安装Golang环境
    什么是Go?  Go是一门并发支持、垃圾回收的编译型的系统编程语言,目的是为了创造一门具有在静态编译语言的高性能和动态语言的高效开发之间拥有良好平衡点的一门编程语言。......
  • golang 发布订阅
    packagemainimport(  "fmt"  "strings"  "sync"  "time"  "github.com/google/uuid")funcNewPubSub()*PubSubTrie{  return&P......
  • Golang中协程调度器底层实现( G、M、P)
    三个必知的核心元素。(G、M、P)G:Goroutine的缩写,一个G代表了对一段需要被执行的Go语言代码的封装M:Machine的缩写,一个M代表了一个内核线程,等同于系统线程P:Processor的缩写......
  • golang 处理文件
    Go语言读取文件的常用方式goReadString()函数分析用FileInfo.sys()获取文件的详细信息......
  • golang中io的使用
    一、读取小文件:ioutil.ReadFile()读取文件的内容并显示在终端(使用ioutil一次将文件读取到内存中),这种方式适用于读取小文件:packagemainimport("fmt""io/iou......
  • golang的GC
    golang采用三色标记法进行垃圾清理GC过程分为标记过程和清理过程产生错误的情况:黑色对象引用白色对象灰色对象到白色对象的引用被破坏破坏这两个条件之一就可以避免......
  • Golang实现hashmap
    golang实现hashmap思路:数组+链表->HashMap1.先看一下go里的map是怎么实现的go实现map采用拉链法的实现,如下图所示,键值对中的键会经过一个哈希函数,哈希函数会帮我们找到......
  • golang接收文件脚本
    golang接收文件脚本packagemainimport("io""os""fmt""io/ioutil""net/http")//https://www.jianshu.com/p/b49cc19d26f0参考资料......
  • golang的编译过程
    编译过程:-----编译前端------词法分析与语法分析类型检查(别的语言中的语义分析,这时候有语法错误才会被找出来)-----编译后端------中间代码生成机器码生成我......