欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go 基于令牌桶的限流器實(shí)現(xiàn)

 更新時間:2021年11月02日 15:48:20   作者:banjming  
如果一般流量過大,下游系統(tǒng)反應(yīng)不過來,這個時候就需要限流了,本文主要介紹了Go 基于令牌桶的限流器實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下

簡介

如果一般流量過大,下游系統(tǒng)反應(yīng)不過來,這個時候就需要限流了,其實(shí)和上地鐵是一樣的,就是減慢上游訪問下游的速度。
限制訪問服務(wù)的頻次或者頻率,防止服務(wù)過載,被刷爆等。

Golang 官方擴(kuò)展包 time(golang.org/x/time/rate) 中,提供了一個基于令牌桶等限流器實(shí)現(xiàn)。

原理概述

  • 令牌:每次拿到令牌,才可訪問
  • 桶 ,桶的最大容量是固定的,以固定的頻率向桶內(nèi)增加令牌,直至加滿
  • 每個請求消耗一個令牌。
  • 限流器初始化的時候,令牌桶一般是滿的。

具體使用

package limiter

import (
 "fmt"
 "testing"
 "time"

 "golang.org/x/time/rate"
)

func TestLimter(t *testing.T) {
 limiter := rate.NewLimiter(rate.Every(time.Millisecond*31), 2)
 //time.Sleep(time.Second)
 for i := 0; i < 10; i++ {
  var ok bool
  if limiter.Allow() {
   ok = true
  }
  time.Sleep(time.Millisecond * 20)
  fmt.Println(ok, limiter.Burst())
 }
}

執(zhí)行結(jié)果:
=== RUN   TestLimter
true 2
true 2
true 2
false 2
true 2
true 2
false 2
true 2
true 2
false 2
--- PASS: TestLimter (0.21s)

通過執(zhí)行結(jié)果可以看到, 令牌桶開始是2個滿的,由于令牌的間隔比請求的間隔多了11ms(31-20), 所以每兩個請求會失敗一次。

具體實(shí)現(xiàn)原理

先看下限流器的創(chuàng)建方法: NewLimiter

func NewLimiter(r Limit, b int) *Limiter {
 return &Limiter{
  limit: r,
  burst: b,
 }
}

查看限流器數(shù)據(jù)結(jié)構(gòu) Limiter

// The methods AllowN, ReserveN, and WaitN consume n tokens.
type Limiter struct {
 mu     sync.Mutex
 limit  Limit
 burst  int
 tokens float64
 // last is the last time the limiter's tokens field was updated
 last time.Time
 // lastEvent is the latest time of a rate-limited event (past or future)
 lastEvent time.Time
}
  • burst 表示了桶的大小
  • limit 表示放入桶的頻率
  • tokens 表示剩余令牌個數(shù)
  • last 最近取走 token 的時間
  • lastEvent 最近限流事件的時間

當(dāng)令牌桶發(fā)放后,會保留在 Reservation 對象中, 定義如下, Reservation 對象,描述了一個達(dá)到 timeToAct 時間后,可以獲取到的令牌的數(shù)量 tokens 數(shù)。

type Reservation struct {
  ok        bool  // 是否滿足條件分配到了tokens
  lim       *Limiter // 發(fā)送令牌的限流器
  tokens    int   // tokens 的數(shù)量
  timeToAct time.Time  //  滿足令牌發(fā)放的時間
  limit Limit  // 令牌發(fā)放速度
}

限流器如何限流

官方提供的限流器有阻塞等待, 也有直接判斷方式的, 還有提供維護(hù)預(yù)留式等。
如何實(shí)現(xiàn)限流的代碼,在 reserveN 中。

使用時,每次都調(diào)用了 Allow() 方法

// Allow is shorthand for AllowN(time.Now(), 1).
func (lim *Limiter) Allow() bool {
 return lim.AllowN(time.Now(), 1)
}

// AllowN reports whether n events may happen at time now.
// Use this method if you intend to drop / skip events that exceed the rate limit.
// Otherwise use Reserve or Wait.
func (lim *Limiter) AllowN(now time.Time, n int) bool {
 return lim.reserveN(now, n, 0).ok
}

繼續(xù)查看 reserverN  算法

方法說明:

  • 三個參數(shù): now, n, maxFutureReserve
  • 在 now 時間需要拿到 n 個令牌,最多等待的時間為 maxFutureReserve
  • 結(jié)果將返回一個預(yù)留令牌的對象 Reservation
// maxFutureReserve specifies the maximum reservation wait duration allowed.
// reserveN returns Reservation, not *Reservation, to avoid allocation in AllowN and WaitN.
func (lim *Limiter) reserveN(now time.Time, n int, maxFutureReserve time.Duration) Reservation {
 lim.mu.Lock()
 // 首先判斷是否放入頻次是否為無窮大,如果為無窮大,說明暫時不限流
 if lim.limit == Inf {
  lim.mu.Unlock()
  return Reservation{
   ok:        true,
   lim:       lim,
   tokens:    n,
   timeToAct: now,
  }
 }
   // 拿到截止 now 時間時,可以獲取的令牌 tokens 數(shù)量,上一次拿走令牌的時間是last
 now, last, tokens := lim.advance(now)

 // Calculate the remaining number of tokens resulting from the request.
 //  更新 tokens數(shù)量,把需要拿走的去掉
 tokens -= float64(n)

 // Calculate the wait duration
 // 如果 tokens 數(shù)量為負(fù)數(shù),說明需要等待,計(jì)算等待時間 WaitDuration
 var waitDuration time.Duration
 if tokens < 0 {
  waitDuration = lim.limit.durationFromTokens(-tokens)
 }

 // Decide result
 // 計(jì)算是否滿足分配要求
 // 1. 需要分配的大小不超過桶容量
 // 2. 等待時間不超過設(shè)定的等待時長
 ok := n <= lim.burst && waitDuration <= maxFutureReserve

 // Prepare reservation
 // 最后構(gòu)造一個 Resvervation 對象
 r := Reservation{
  ok:    ok,
  lim:   lim,
  limit: lim.limit,
 }
 if ok {
  r.tokens = n
  r.timeToAct = now.Add(waitDuration)
 }

 // Update state
   // 需要更新當(dāng)前 limit 的值 
 if ok {
  lim.last = now
  lim.tokens = tokens
  lim.lastEvent = r.timeToAct
 } else {
  lim.last = last
 }

 lim.mu.Unlock()
 return r
}

從實(shí)現(xiàn)上看, limiter 并不是每隔一段時間更新當(dāng)前桶的數(shù)量,而是記錄了上次訪問時和當(dāng)前桶中令牌的數(shù)量,當(dāng)再次訪問時,通過上次訪問時間計(jì)算出當(dāng)前令牌的數(shù)量,決定是否可以發(fā)放令牌。

到此這篇關(guān)于Go 基于令牌桶的限流器實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Go 令牌桶限流器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • Golang channle管道的基本使用及快速入門

    Golang channle管道的基本使用及快速入門

    管道是Go語言中實(shí)現(xiàn)并發(fā)的一種方式,它可以在多個goroutine之間進(jìn)行通信和數(shù)據(jù)交換,本文主要介紹了Golang channle管道的基本使用及快速入門,具有一定的參考價值,感興趣的可以了解一下
    2023-12-12
  • Go語言自定義linter靜態(tài)檢查工具

    Go語言自定義linter靜態(tài)檢查工具

    這篇文章主要介紹了Go語言自定義linter靜態(tài)檢查工具,Go語言是一門編譯型語言,編譯器將高級語言翻譯成機(jī)器語言,會先對源代碼做詞法分析,詞法分析是將字符序列轉(zhuǎn)換為Token序列的過程,文章詳細(xì)介紹需要的小伙伴可以參考一下
    2022-05-05
  • Go語言的JSON處理詳解

    Go語言的JSON處理詳解

    json格式可以算我們?nèi)粘W畛S玫男蛄谢袷街涣?Go語言作為一個由Google開發(fā),號稱互聯(lián)網(wǎng)的C語言的語言,自然也對JSON格式支持很好。
    2018-10-10
  • golang使用json格式實(shí)現(xiàn)增刪查改的實(shí)現(xiàn)示例

    golang使用json格式實(shí)現(xiàn)增刪查改的實(shí)現(xiàn)示例

    這篇文章主要介紹了golang使用json格式實(shí)現(xiàn)增刪查改的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • Go?panic的三種產(chǎn)生方式細(xì)節(jié)探究

    Go?panic的三種產(chǎn)生方式細(xì)節(jié)探究

    這篇文章主要介紹了Go?panic的三種產(chǎn)生方式細(xì)節(jié)探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • Golang的Crypto/SHA256庫實(shí)戰(zhàn)指南

    Golang的Crypto/SHA256庫實(shí)戰(zhàn)指南

    無論是在保護(hù)數(shù)據(jù)安全、驗(yàn)證數(shù)據(jù)完整性,還是在構(gòu)建復(fù)雜的安全系統(tǒng)中,crypto/sha256都是Golang程序員不可或缺的工具,本文主要介紹了Golang的Crypto/SHA256庫實(shí)戰(zhàn)指南,感興趣的可以了解一下
    2024-02-02
  • Golang Web 框架Iris安裝部署

    Golang Web 框架Iris安裝部署

    這篇文章主要為大家介紹了Golang Web 框架Iris安裝部署,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Go語言中Goroutine的設(shè)置方式

    Go語言中Goroutine的設(shè)置方式

    這篇文章介紹了Go語言中Goroutine的設(shè)置方式,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-07-07
  • go?tar包歸檔文件處理操作全面指南

    go?tar包歸檔文件處理操作全面指南

    這篇文章主要為大家介紹了使用go?tar包歸檔文件處理操作全面指南,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • Golang中生成隨機(jī)字符串并復(fù)制到粘貼板的方法

    Golang中生成隨機(jī)字符串并復(fù)制到粘貼板的方法

    這篇文章主要介紹了Golang中生成隨機(jī)字符串并復(fù)制到粘貼板的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12

最新評論