用更簡單的話來說,速率限制,它是一種限制使用者或客戶端在給定時間範圍內可以向 API 發出請求數量的技術。過去,當您嘗試存取天氣或笑話 API 時,您可能遇到過收到「超出速率限制」訊息的情況。關於為什麼要限制 API 的速率有很多爭論,但一些重要的爭論是合理使用它、確保其安全性、保護資源免於過載等。
在本部落格中,我們將使用 Gin 框架使用 Golang 建立一個 HTTP 伺服器,使用 Redis 對端點應用速率限制功能,並儲存某個時間範圍內 IP 向伺服器發出的請求總數。如果超過我們設定的限制,我們會給出錯誤訊息。
如果你不知道 Gin 和 Redis 是什麼。 Gin 是一個用 Golang 寫的 Web 框架。它有助於創建一個簡單而快速的伺服器,而無需編寫大量程式碼。 Redis 它是一個記憶體中的鍵值資料存儲,可以用作資料庫或快取功能。
先決條件
- 熟悉 Golang、Gin 和 Redis
- 一個 Redis 實例(我們可以使用 Docker 或遠端機器)
現在,讓我們開始吧。
要初始化項目,請執行 go mod init
然後讓我們使用 Gin 框架建立一個簡單的 HTTP 伺服器,然後套用對其進行速率限制的邏輯。您可以複製下面的程式碼。這是非常基本的。當我們點擊 /message 端點時,伺服器將回覆一則訊息。
複製以下程式碼後,執行 go mod tidy 即可自動安裝我們匯入的軟體包。
package main import ( "github.com/gin-gonic/gin" ) func main() { r := gin.Default() r.GET("/message", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "You can make more requests", }) }) r.Run(":8081") //listen and serve on localhost:8081 }
我們可以透過在終端機中執行 go run main.go 來運行伺服器,並在終端機中看到此訊息。
要測試它,我們可以存取 localhost:8081/message 我們將在瀏覽器中看到此訊息。
現在我們的伺服器正在運行,讓我們為 /message 路由設定速率限制功能。我們將使用 go-redis/redis_rate 套件。感謝這個套件的創建者,我們不需要從頭開始編寫處理和檢查限制的邏輯。它將為我們完成所有繁重的工作。
以下是實現限速功能後的完整程式碼。我們會理解其中的每一點。只是儘早給出完整的程式碼,以避免任何混淆並了解不同部分如何協同工作。
複製程式碼後,執行 go mod tidy 來安裝所有匯入的軟體包。現在讓我們跳轉並理解程式碼(在程式碼片段下方)。
package main import ( "github.com/gin-gonic/gin" ) func main() { r := gin.Default() r.GET("/message", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "You can make more requests", }) }) r.Run(":8081") //listen and serve on localhost:8081 }
我們先直接跳到rateLimiter()函數來理解一下。該函數需要一個參數,即請求的 IP 位址,我們可以透過主函數中的 c.ClientIP() 來取得該位址。如果達到限制,我們將傳回錯誤,否則將其保持為零。大部分程式碼是我們從官方 GitHub 儲存庫中取得的樣板程式碼。這裡需要仔細研究的關鍵功能是 limiter.Allow() 函數。 Addr:取得 Redis 實例的 URL 路徑值。我正在使用 Docker 在本地運行它。您可以使用任何內容,只需確保相應地替換 URL 即可。
package main import ( "context" "errors" "net/http" "github.com/gin-gonic/gin" "github.com/go-redis/redis_rate/v10" "github.com/redis/go-redis/v9" ) func main() { r := gin.Default() r.GET("/message", func(c *gin.Context) { err := rateLimiter(c.ClientIP()) if err != nil { c.JSON(http.StatusTooManyRequests, gin.H{ "message": "you have hit the limit", }) return } c.JSON(http.StatusOK, gin.H{ "message": "You can make more requests", }) }) r.Run(":8081") } func rateLimiter(clientIP string) error { ctx := context.Background() rdb := redis.NewClient(&redis.Options{ Addr: "localhost:6379", }) limiter := redis_rate.NewLimiter(rdb) res, err := limiter.Allow(ctx, clientIP, redis_rate.PerMinute(10)) if err != nil { panic(err) } if res.Remaining == 0 { return errors.New("Rate") } return nil }
它有三個參數,第一個是 ctx,第二個是 Key,Redis 資料庫的 Key(值的鍵),第三個是限制。因此,函數將 clientIP 位址儲存為鍵,將預設限制儲存為值,並在發出請求時減少它。這種結構的原因是Redis資料庫需要唯一標識和唯一鍵來儲存鍵值對類型的數據,並且每個IP位址都以自己的方式唯一,這就是為什麼我們使用IP位址而不是用戶名,第三個參數redis_rate.PerMinute(10) 可以依照我們的需求進行修改,我們可以設定限制PerSecond, PerHour,等等,並設定括號內的值,表示每分鐘/秒/小時可以發出多少個請求。在我們的例子中,它是每分鐘 10 個。是的,設定就這麼簡單。
最後,我們透過 res.Remaining 檢查是否有剩餘配額。如果它為零,我們將返回錯誤訊息,否則我們將返回 nil。例如,您也可以執行 res.Limit.Rate 來檢查限制率等。您可以嘗試並深入研究它。
現在是 main() 函數:
res, err := limiter.Allow(ctx, clientIP, redis_rate.PerMinute(10))
一切都幾乎一樣。在 /message 路由中,現在每次路由命中時,我們都會呼叫rateLimit()函數並向其傳遞一個 ClientIP 位址,並將傳回值(錯誤)值儲存在 err 變數中。如果發生錯誤,我們將回傳 429,即 http.StatusTooManyRequests,以及一則訊息「message」:「您已達到限制」。如果該人有剩餘限制並且rateLimit()沒有返回錯誤,它將正常工作,就像之前所做的那樣並服務於請求。
這就是所有的解釋。現在讓我們測試一下工作情況。透過執行相同的命令重新運行伺服器。我們將第一次看到之前收到的相同訊息。現在刷新您的瀏覽器 10 次(因為我們設定了每分鐘 10 次的限制),您將在瀏覽器中看到錯誤訊息。
我們也可以透過查看終端機中的日誌來驗證這一點。 Gin 提供了很好的開箱即用的登入功能。一分鐘後它將恢復我們的限製配額。
本部落格到此結束,我希望您喜歡閱讀,就像我喜歡寫這篇文章一樣。我很高興您能堅持到最後,非常感謝您的支持。我還經常在 X (Twitter) 上談論 Golang 以及其他內容,例如開源和 Docker。你可以在那裡聯絡我。
以上是使用 Redis 對 Golang API 進行速率限制的詳細內容。更多資訊請關注PHP中文網其他相關文章!

掌握Go語言中的strings包可以提高文本處理能力和開發效率。 1)使用Contains函數檢查子字符串,2)用Index函數查找子字符串位置,3)Join函數高效拼接字符串切片,4)Replace函數替換子字符串。注意避免常見錯誤,如未檢查空字符串和大字符串操作性能問題。

你應該關心Go語言中的strings包,因為它能簡化字符串操作,使代碼更清晰高效。 1)使用strings.Join高效拼接字符串;2)用strings.Fields按空白符分割字符串;3)通過strings.Index和strings.LastIndex查找子串位置;4)用strings.ReplaceAll進行字符串替換;5)利用strings.Builder進行高效字符串拼接;6)始終驗證輸入以避免意外結果。

thestringspackageingoisesential forefficientstringManipulation.1)itoffersSimpleyetpoperfulfunctionsFortaskSlikeCheckingSslingSubstringsStringStringsStringsandStringsN.2)ithandhishiCodeDewell,withFunctionsLikestrings.fieldsfieldsfieldsfordsforeflikester.fieldsfordsforwhitespace-fieldsforwhitespace-separatedvalues.3)3)

WhendecidingbetweenGo'sbytespackageandstringspackage,usebytes.Bufferforbinarydataandstrings.Builderforstringoperations.1)Usebytes.Bufferforworkingwithbyteslices,binarydata,appendingdifferentdatatypes,andwritingtoio.Writer.2)Usestrings.Builderforstrin

Go的strings包提供了多種字符串操作功能。 1)使用strings.Contains檢查子字符串。 2)用strings.Split將字符串分割成子字符串切片。 3)通過strings.Join合併字符串。 4)用strings.TrimSpace或strings.Trim去除字符串首尾的空白或指定字符。 5)用strings.ReplaceAll替換所有指定子字符串。 6)使用strings.HasPrefix或strings.HasSuffix檢查字符串的前綴或後綴。

使用Go語言的strings包可以提升代碼質量。 1)使用strings.Join()優雅地連接字符串數組,避免性能開銷。 2)結合strings.Split()和strings.Contains()處理文本,注意大小寫敏感問題。 3)避免濫用strings.Replace(),考慮使用正則表達式進行大量替換。 4)使用strings.Builder提高頻繁拼接字符串的性能。

Go的bytes包提供了多種實用的函數來處理字節切片。 1.bytes.Contains用於檢查字節切片是否包含特定序列。 2.bytes.Split用於將字節切片分割成smallerpieces。 3.bytes.Join用於將多個字節切片連接成一個。 4.bytes.TrimSpace用於去除字節切片的前後空白。 5.bytes.Equal用於比較兩個字節切片是否相等。 6.bytes.Index用於查找子切片在largerslice中的起始索引。

theEncoding/binarypackageingoisesenebecapeitProvidesAstandArdArdArdArdArdArdArdArdAndWriteBinaryData,確保Cross-cross-platformCompatibilitiational and handhandlingdifferentendenness.itoffersfunctionslikeread,寫下,寫,dearte,readuvarint,andwriteuvarint,andWriteuvarIntforPreciseControloverBinary


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

SublimeText3 Linux新版
SublimeText3 Linux最新版

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

禪工作室 13.0.1
強大的PHP整合開發環境

SAP NetWeaver Server Adapter for Eclipse
將Eclipse與SAP NetWeaver應用伺服器整合。

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器