go基于Gin框架的HTTP接口限速實踐
在當(dāng)今的微服務(wù)架構(gòu)和RESTful API主導(dǎo)的時代,HTTP接口在各個業(yè)務(wù)模塊之間扮演著重要的角色。隨著業(yè)務(wù)規(guī)模的不斷擴大,接口的訪問頻率和負(fù)載也隨之增加。為了確保系統(tǒng)的穩(wěn)定性和性能,接口限速成了一個重要的話題。
1 接口限速的使用場景
接口限速的使用場景主要涉及以下幾種情況:
- 防止API濫用:在某些情況下,如果沒有有效的限速機制,惡意用戶可能會無限制地調(diào)用API,導(dǎo)致系統(tǒng)過載。通過接口限速,我們可以限制每個用戶對特定接口的訪問頻率,從而防止API濫用。
- 保護服務(wù)穩(wěn)定性:在某些情況下,某些高頻調(diào)用可能會給后端服務(wù)帶來巨大的壓力,影響服務(wù)的穩(wěn)定性和性能。通過接口限速,我們可以限制對這些接口的訪問頻率,從而保護服務(wù)的穩(wěn)定性。
- 資源合理分配:在一些情況下,我們需要對系統(tǒng)資源進行合理的分配,確保每個用戶都能得到公平的資源使用。通過接口限速,我們可以根據(jù)用戶的請求頻率進行資源分配,從而保證公平性。
2 限速不同與限流
接口限速和限流是兩個不同的概念,雖然它們都是用來控制流量和保護系統(tǒng)的手段,但它們的目的和實現(xiàn)方式有所不同。
接口限速主要是限制接口的訪問速度,避免過快的請求頻率對系統(tǒng)造成壓力。它關(guān)注的是單個接口的訪問速率,比如每秒可以訪問多少次,而限流則是關(guān)注系統(tǒng)的整體流量,限制單位時間內(nèi)系統(tǒng)的總訪問量。
限速通常是通過在接口上設(shè)置速率限制來實現(xiàn)的,例如使用令牌桶算法或漏桶算法等。它的主要目的是防止單個接口的過快訪問,以保護系統(tǒng)的穩(wěn)定性和性能。
而限流則是通過一系列機制來限制單位時間內(nèi)系統(tǒng)的總訪問量,以防止系統(tǒng)過載。常見的限流算法包括令牌桶算法、漏桶算法和熱點參數(shù)等。它的主要目的是保護整個系統(tǒng),避免因為訪問量過大而出現(xiàn)崩潰或性能下降的情況。
在實現(xiàn)方面,限速通常是在應(yīng)用程序或API網(wǎng)關(guān)層面實現(xiàn)的,而限流則可能需要涉及到整個系統(tǒng)的架構(gòu)和設(shè)計。
雖然接口限速和限流的目的和實現(xiàn)方式有所不同,但它們都是為了控制流量和保護系統(tǒng)的穩(wěn)定性和性能。在實際應(yīng)用中,我們可以根據(jù)實際情況選擇合適的限速和限流策略,以實現(xiàn)最佳的流量控制效果。
3 Gin框架接口限速實踐
基于limiter插件的GitHub地址:github.com/ulule/limiter
3.1 基本使用
package main
import (
"fmt"
"log"
"net/http"
"github.com/gin-gonic/gin"
"github.com/redis/go-redis/v9"
"github.com/ulule/limiter/v3"
mgin "github.com/ulule/limiter/v3/drivers/middleware/gin"
sredis "github.com/ulule/limiter/v3/drivers/store/redis"
)
func main() {
// Define a limit rate to 4 requests per hour.
rate, err := limiter.NewRateFromFormatted("4-M")
if err != nil {
log.Fatal(err)
return
}
// Create a redis client.
option, err := redis.ParseURL("redis://localhost:6379/0")
if err != nil {
log.Fatal(err)
return
}
client := redis.NewClient(option)
// Create a store with the redis client.
store, err := sredis.NewStoreWithOptions(client, limiter.StoreOptions{
Prefix: "limiter_gin_example",
MaxRetry: 3,
})
if err != nil {
log.Fatal(err)
return
}
// Create a new middleware with the limiter instance.
middleware := mgin.NewMiddleware(limiter.New(store, rate))
// Launch a simple server.
router := gin.Default()
router.ForwardedByClientIP = true
router.Use(middleware)
router.GET("/", index)
log.Fatal(router.Run(":8081"))
}
func index(c *gin.Context) {
c.JSON(http.StatusOK, "This is my gin api...")
}3.2 引入自定義攔截處理器
package main
import (
"fmt"
"log"
"net/http"
"github.com/gin-gonic/gin"
"github.com/redis/go-redis/v9"
"github.com/ulule/limiter/v3"
mgin "github.com/ulule/limiter/v3/drivers/middleware/gin"
sredis "github.com/ulule/limiter/v3/drivers/store/redis"
)
func main() {
rate, err := limiter.NewRateFromFormatted("4-M")
if err != nil {
log.Fatal(err)
return
}
option, err := redis.ParseURL("redis://localhost:6379/0")
if err != nil {
log.Fatal(err)
return
}
client := redis.NewClient(option)
store, err := sredis.NewStoreWithOptions(client, limiter.StoreOptions{
Prefix: "limiter_gin_example",
MaxRetry: 3,
})
if err != nil {
log.Fatal(err)
return
}
//自定義攔截處理器
opt := mgin.WithLimitReachedHandler(ExceededHandler)
middleware := mgin.NewMiddleware(limiter.New(store, rate), opt)
router := gin.Default()
router.ForwardedByClientIP = true
router.Use(middleware)
router.GET("/", index)
log.Fatal(router.Run(":8081"))
}
func ExceededHandler(c *gin.Context) {
c.JSON(200, "This is mu custom ExceededHandler...")
}
func index(c *gin.Context) {
c.JSON(http.StatusOK, "This is my gin api...")
}返回結(jié)果:

3.3 不同接口區(qū)分速率
我們假設(shè)系統(tǒng)有兩個接口:
- /fast : 每分鐘允許10次訪問
- /slow : 每分鐘允許1次訪問
代碼實現(xiàn):
package main
import (
"fmt"
"log"
"net/http"
"github.com/gin-gonic/gin"
"github.com/redis/go-redis/v9"
"github.com/ulule/limiter/v3"
mgin "github.com/ulule/limiter/v3/drivers/middleware/gin"
sredis "github.com/ulule/limiter/v3/drivers/store/redis"
)
var (
fastTime = 0
slowTime = 0
)
func FastApi(c *gin.Context) {
fastTime += 1
c.JSON(200, fmt.Sprintf("This is fast api... %d", fastTime))
}
func SlowApi(c *gin.Context) {
slowTime += 1
c.JSON(200, fmt.Sprintf("This is slow api... %d", slowTime))
}
func main() {
fastRate, err := limiter.NewRateFromFormatted("10-M")
if err != nil {
log.Fatal(err)
return
}
slowRate, err := limiter.NewRateFromFormatted("1-M")
if err != nil {
log.Fatal(err)
return
}
option, err := redis.ParseURL("redis://localhost:6379/0")
if err != nil {
log.Fatal(err)
return
}
client := redis.NewClient(option)
storeFast, err := sredis.NewStoreWithOptions(client, limiter.StoreOptions{Prefix: "limiter_gin_example_fast", MaxRetry: 3})
if err != nil {
log.Fatal(err)
return
}
storeSlow, err := sredis.NewStoreWithOptions(client, limiter.StoreOptions{Prefix: "limiter_gin_example_slow", MaxRetry: 3})
if err != nil {
log.Fatal(err)
return
}
//自定義攔截處理器
opt := mgin.WithLimitReachedHandler(ExceededHandler)
middlewareFast := mgin.NewMiddleware(limiter.New(storeFast, fastRate), opt)
middlewareSlow := mgin.NewMiddleware(limiter.New(storeSlow, slowRate), opt)
router := gin.Default()
router.ForwardedByClientIP = true
router.Use(func(c *gin.Context) {
if c.Request.RequestURI == "/fast" {
middlewareFast(c)
return
}
if c.Request.RequestURI == "/slow" {
middlewareSlow(c)
return
}
})
router.GET("/fast", FastApi)
router.GET("/slow", SlowApi)
log.Fatal(router.Run(":8081"))
}
func ExceededHandler(c *gin.Context) {
c.JSON(200, "This is mu custom ExceededHandler...")
}4 小總結(jié)
接口限速是保護系統(tǒng)穩(wěn)定性和API的重要手段。在實際應(yīng)用中,我們需要根據(jù)實際情況選擇合適的限速方法,實現(xiàn)對接口的全面限速。通過接口限速,我們可以提高系統(tǒng)的穩(wěn)定性、保護API、提高用戶體驗等。
到此這篇關(guān)于go基于Gin框架的HTTP接口限速實踐的文章就介紹到這了,更多相關(guān)Gin HTTP接口限速內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
golang?db事務(wù)的統(tǒng)一封裝的實現(xiàn)
這篇文章主要介紹了golang db事務(wù)的統(tǒng)一封裝的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-12-12
Golang?基于flag庫實現(xiàn)一個簡單命令行工具
這篇文章主要介紹了Golang基于flag庫實現(xiàn)一個簡單命令行工具,Golang標(biāo)準(zhǔn)庫中的flag庫提供了解析命令行選項的能力,我們可以基于此來開發(fā)命令行工具,下文詳細(xì)介紹。需要的小伙伴可以參考一下2022-08-08
golang實現(xiàn)微信小程序商城后臺系統(tǒng)(moshopserver)
這篇文章主要介紹了golang實現(xiàn)微信小程序商城后臺系統(tǒng)(moshopserver),本文通過截圖實例代碼的形式給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2020-02-02
Golang的循環(huán)語句和循環(huán)控制語句詳解
循環(huán)語句為了簡化程序中有規(guī)律的重復(fù)性操作,需要用到循環(huán)語句,和其他大多數(shù)編程語言一樣,GO的循環(huán)語句有for循環(huán),不同的是沒有while循環(huán),而循環(huán)控制語句可以改變循環(huán)語句的執(zhí)行過程,下面給大家介紹下go循環(huán)語句和循環(huán)控制語句的相關(guān)知識,一起看看吧2021-11-11

