網(wǎng)站首頁 編程語言 正文
前言
在我們的日常開發(fā)中, 常用的中間件有很多, 今天來講一下怎么集成限流中間件, 它可以很好地用限制并發(fā)訪問數(shù)來保護系統(tǒng)服務, 避免系統(tǒng)服務崩潰, 資源占用過大甚至服務器崩潰進而影響到其他應用!
分布式版
簡介
通常我們的服務會同時存在多個進程, 也就是負載來保證服務的性能和穩(wěn)定性, 那么就需要走一個統(tǒng)一的限流, 這個時候就需要借助我們的老朋友-redis
, 來進行分布式限流;
算法
漏桶算法
即一個水桶, 進水(接受請求)的速率不限, 出水(處理請求)的速率是一定的, 如果出水的速率小于進水的速率, 就會造成水桶溢出(也就是拒絕請求); 主要是從出口限制, 以固定的速率控制訪問速度, 缺點是難以應對突發(fā)請求;
實現(xiàn)
下面是一個簡單的實現(xiàn), 對 /v1/hello
接口進行每分鐘2次的速率限制
// RateLimitConf 速率配置, 允許多長時間通過多少次. type RateLimitConf struct { Limit int64 Timer time.Duration } // exampleLimiterMap 接口請求速率配置, 建議放入redis/數(shù)據(jù)庫同步本地緩存. var exampleLimiterMap = map[string]RateLimitConf{ "/v1/hello": {Limit: 2, Timer: time.Minute}, } // LimiterMiddle 分布式限流中間件. func LimiterMiddle(ctx iris.Context) { var ( uri = ctx.Request().RequestURI client = redis.NewClusterClient() key = uri ) conf, ok := exampleLimiterMap[uri] if ok { limiter := redis_rate.NewLimiter(client) if _, _, b := limiter.Allow(key, conf.Limit, conf.Timer); !b { r, _ := httpcode.NewRequest(ctx, nil) r.Code(httpcode.TooManyReq, fmt.Errorf("req rate limit"), nil) return } } ctx.Next() }
注意
- 接口速率配置如果需要進行實時配置, 則建議將配置寫入數(shù)據(jù)庫, 然后刷新到本地緩存/存到redis;
- 如果需要對設備/ip/用戶進行接口限制訪問, 則將
key
加上唯一標志即可;
單機版
簡介
這個就只適用于單個服務進程的限流, 比如個人搭的一些小網(wǎng)站之類的;
算法
令牌桶算法
即也是一個桶, 按照設定的速率往桶里放令牌, 10s二十次即1s放兩個令牌(允許處理兩次請求), 然后請求來之后必須從桶里取出來令牌才可以進行處理, 沒有令牌則選擇拒絕或等待; 主要是從入口限制, 允許一定量的突發(fā)請求(即桶內(nèi)所有的令牌);
依賴庫
golang.org/x/time/rate
實現(xiàn)
下面是一個簡單的實現(xiàn), 對 /v1/hello
接口進行每分鐘2次的速率限制
// exampleStandAloneLimiterMap 單機接口請求速率配置. var exampleStandAloneLimiterMap = map[string]*rate.Limiter{ "/v1/hello": rate.NewLimiter(rate.Every(time.Minute), 2), } // StandAloneLimiterMiddle 單機限流中間件. func StandAloneLimiterMiddle(ctx iris.Context) { var ( uri = ctx.Request().RequestURI ) limiter, ok := exampleStandAloneLimiterMap[uri] if ok { if b := limiter.Allow(); !b { r, _ := httpcode.NewRequest(ctx, nil) r.Code(httpcode.TooManyReq, fmt.Errorf("req rate limit"), nil) return } } ctx.Next() }
結語
上面的代碼均摘自我開發(fā)的一個開源項目中, 主要是一個Go的標準項目布局, 封裝了一些常用的組件, 有興趣的朋友可以了解一下, 新手極易上手;
原文鏈接:https://juejin.cn/post/7140108558120517669
相關推薦
- 2022-08-06 python練習之循環(huán)控制語句?break?與?continue_python
- 2022-04-14 詳細聊聊C#的并發(fā)機制優(yōu)秀在哪_C#教程
- 2022-05-19 徹底解決No?module?named?‘torch_geometric‘報錯的辦法_python
- 2023-01-19 Go定時器的三種實現(xiàn)方式示例詳解_Golang
- 2022-11-17 淺析golang的依賴注入_Golang
- 2022-10-05 jQuery編程動畫的基本方法示例詳解_jquery
- 2022-07-21 微信小程序--動態(tài)設置導航欄顏色
- 2022-07-29 django?restframework序列化字段校驗規(guī)則_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結構-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支