最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go 如何基于IP限制HTTP訪問頻率的方法實現(xiàn)

 更新時間:2019年11月25日 09:45:51   投稿:zx  
這篇文章主要介紹了Go 如何基于IP限制HTTP訪問頻率的方法實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

如果你運行 HTTP 服務,并且希望限制 HTTP 的訪問頻率,那么你可以借助一些比較穩(wěn)定的工具,例如: github.com/didip/tollbooth。不過如果你構建的應用比較簡單,也可以自己來實現(xiàn)。

我們可以使用一個現(xiàn)有的 Go 包 x/time/rate。

本課程,我們將創(chuàng)建一個簡單的中間件實現(xiàn)基于 IP 限制 HTTP 訪問頻率。

簡單的 HTTP 服務

讓我們從創(chuàng)建一個簡單的 HTTP 服務開始,它有非常簡單的終端。 但是,因為它的訪問頻率可能非常高,因此我們要為它添加頻率限制。

package main

import (
 "log"
 "net/http"
)

func main() {
 mux := http.NewServeMux()
 mux.HandleFunc("/", okHandler)

 if err := http.ListenAndServe(":8888", mux); err != nil {
  log.Fatalf("unable to start server: %s", err.Error())
 }
}

func okHandler(w http.ResponseWriter, r *http.Request) {
 // 某些消耗很高的數(shù)據(jù)庫請求
 w.Write([]byte("alles gut"))
}

通過 main.go 我們啟動服務,監(jiān)聽 :8888 端口,這樣我們就有了一個簡單的終端 /。

golang.org/x/time/rate

我們將使用名為 x/time/rate 的 Go 包,它提供了一個令牌桶速率限制器算法。rate#Limiter 控制允許事件發(fā)生的頻率。它實現(xiàn)了一個大小為 b 的「令牌桶」,最初是滿的,并以每秒 r 的速度重新填充令牌。通俗地講,就是在任何足夠大的時間間隔內(nèi),限制器將速率限制為每秒 r 個令牌,最大突發(fā)大小為 b 個事件。

由于我們希望實現(xiàn)每個 IP 地址的速率限制器,我們還需要維護一個限制器映射。

package main

import (
 "sync"

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

// IPRateLimiter .
type IPRateLimiter struct {
 ips map[string]*rate.Limiter
 mu *sync.RWMutex
 r rate.Limit
 b int
}

// NewIPRateLimiter .
func NewIPRateLimiter(r rate.Limit, b int) *IPRateLimiter {
 i := &IPRateLimiter{
  ips: make(map[string]*rate.Limiter),
  mu: &sync.RWMutex{},
  r: r,
  b: b,
 }

 return i
}

// AddIP 創(chuàng)建了一個新的速率限制器,并將其添加到 ips 映射中,
// 使用 IP地址作為密鑰
func (i *IPRateLimiter) AddIP(ip string) *rate.Limiter {
 i.mu.Lock()
 defer i.mu.Unlock()

 limiter := rate.NewLimiter(i.r, i.b)

 i.ips[ip] = limiter

 return limiter
}

// GetLimiter 返回所提供的IP地址的速率限制器(如果存在的話).
// 否則調(diào)用 AddIP 將 IP 地址添加到映射中
func (i *IPRateLimiter) GetLimiter(ip string) *rate.Limiter {
 i.mu.Lock()
 limiter, exists := i.ips[ip]

 if !exists {
  i.mu.Unlock()
  return i.AddIP(ip)
 }

 i.mu.Unlock()

 return limiter
}

NewIPRateLimiter 創(chuàng)建一個 IP 限制器實例,HTTP 服務器必須調(diào)用這個實例的 GetLimiter 來獲得指定 IP 的限制器 (從映射或生成一個新的)。

中間件

讓我們升級的 HTTP 服務并將中間件添加到所有端點,如果 IP 達到限制,它將響應 429 Too Many Requests,否則,它將繼續(xù)該請求。

每一個經(jīng)過中間件的請求,我們都會調(diào)用 limitMiddleware 函數(shù)中的全局方法 Allow()。如果存儲桶中沒有令牌了,該方法會返回 false,該請求會收到 429 Too Many Requests 的響應。否則 Allow() 方法將消耗一個令牌,并將請求傳遞給下一個程序。

package main

import (
 "log"
 "net/http"
)

var limiter = NewIPRateLimiter(1, 5)

func main() {
 mux := http.NewServeMux()
 mux.HandleFunc("/", okHandler)

 if err := http.ListenAndServe(":8888", limitMiddleware(mux)); err != nil {
  log.Fatalf("unable to start server: %s", err.Error())
 }
}

func limitMiddleware(next http.Handler) http.Handler {
 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  limiter := limiter.GetLimiter(r.RemoteAddr)
  if !limiter.Allow() {
   http.Error(w, http.StatusText(http.StatusTooManyRequests), http.StatusTooManyRequests)
   return
  }

  next.ServeHTTP(w, r)
 })
}

func okHandler(w http.ResponseWriter, r *http.Request) {
 // 非常重要的數(shù)據(jù)請求(譯者注:這句話沒理解到位)
 w.Write([]byte("alles gut"))
}

編譯 & 執(zhí)行

go get golang.org/x/time/rate
go build -o server .
./server

測試

這是我喜歡使用的一個非常好的來進行 HTTP 負載測試的工具,它叫做 vegeta (它也是用 Go 編寫的)。

brew install vegeta

我們需要創(chuàng)建一個簡單的配置文件,來展示我們希望生成的請求。

GET http://localhost:8888/

然后運行攻擊 10 秒,每個時間單位 100 個請求。

vegeta attack -duration=10s -rate=100 -targets=vegeta.conf | vegeta report

結果,您將看到一些請求返回了 200,但是大多數(shù)都返回了 429。

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • Go語言調(diào)用ffmpeg-api實現(xiàn)音頻重采樣

    Go語言調(diào)用ffmpeg-api實現(xiàn)音頻重采樣

    最近對golang處理音視頻很感興趣,對golang音視頻常用庫goav進行了一番研究。自己寫了一個wav轉采樣率的功能。給大家分享一下,中間遇到了不少坑,解決的過程中還是蠻有意思的,希望大家能喜歡
    2022-12-12
  • 探索Go語言中的switch高級用法

    探索Go語言中的switch高級用法

    在Go語言中,switch語句除了常見的用法外,還有一種不常用但有趣的寫法,這種寫法中,switch后面不跟任何表達式,而每個case后面跟的是返回bool類型的函數(shù)調(diào)用表達式,這實際上是一個等價于switch true的用法,通過從上到下逐一比較case后的表達式是否為true來決定執(zhí)行哪個分支
    2024-10-10
  • golang封裝一個執(zhí)行命令行的函數(shù)(return?stderr/stdout/exitcode)示例代碼

    golang封裝一個執(zhí)行命令行的函數(shù)(return?stderr/stdout/exitcode)示例代碼

    在?Go?語言中,您可以使用?os/exec?包來執(zhí)行外部命令,不通過調(diào)用?shell,并且能夠獲得進程的退出碼、標準輸出和標準錯誤輸出,下面給大家分享golang封裝一個執(zhí)行命令行的函數(shù)(return?stderr/stdout/exitcode)的方法,感興趣的朋友跟隨小編一起看看吧
    2024-06-06
  • 詳解Golang使用MongoDB通用操作

    詳解Golang使用MongoDB通用操作

    這篇文章主要介紹了詳解Golang使用MongoDB通用操作,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12
  • 詳解Golang語言HTTP客戶端實踐

    詳解Golang語言HTTP客戶端實踐

    本文主要介紹了Golang語言HTTP客戶端實踐,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • Go指針的具體使用

    Go指針的具體使用

    本文主要介紹了Go指針的具體使用,包括使用指針、空指針、指針數(shù)組、指向指針的指針等,具有一定的參考價值,感興趣的可以了解一下
    2023-11-11
  • 分析Go語言接口的設計原則

    分析Go語言接口的設計原則

    interface是Go語言的基礎特性之一, 可以理解為對一種類型的規(guī)范或者約束。他跟java、c++不同, Go語言實現(xiàn)接口不需要顯示說明實現(xiàn)了哪個接口, 也沒有繼承或者子類或者implement關鍵字。只是通過約定的形式, 隱式的實現(xiàn)接口中的方法即可
    2021-06-06
  • Golang Gin框架實現(xiàn)多種數(shù)據(jù)格式返回結果詳解

    Golang Gin框架實現(xiàn)多種數(shù)據(jù)格式返回結果詳解

    這篇文章主要介紹了Golang Gin框架實現(xiàn)多種數(shù)據(jù)格式返回結果,我們都知道,一個完整的請求包含請求和處理請求以及結果返回三個步驟,在服務器端對請求處理完成以后,會將結果返回給客戶端,在gin框架中,支持返回多種請求數(shù)據(jù)格式,下面我們一起來看看
    2023-05-05
  • go?defer?return?panic?執(zhí)行順序示例詳解

    go?defer?return?panic?執(zhí)行順序示例詳解

    這篇文章主要介紹了go?defer?return?panic?執(zhí)行順序,本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-01-01
  • 使用Golang快速構建出命令行應用程序

    使用Golang快速構建出命令行應用程序

    在日常開發(fā)中,大家對命令行工具(CLI)想必特別熟悉了,如果說你不知道命令工具,那你可能是個假開發(fā)。每天都會使用大量的命令行工具,例如最常用的Git、Go、Docker等,這篇文章主要介紹了使用Golang快速構建出命令行應用程序,需要的朋友可以參考下
    2023-02-02

最新評論

石台县| 尤溪县| 平阳县| 翁源县| 柳州市| 沙田区| 天水市| 措美县| 孟州市| 抚宁县| 勃利县| 边坝县| 天台县| 定日县| 读书| 晋宁县| 焦作市| 德格县| 尚志市| 朔州市| 丹阳市| 万载县| 晋宁县| 宝鸡市| 鸡泽县| 杭锦后旗| 陵水| 蚌埠市| 永顺县| 石河子市| 尚义县| 崇明县| 蒙阴县| 富裕县| 太谷县| 江孜县| 射洪县| 彭山县| 清新县| 芦溪县| 沽源县|