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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM