網站首頁 編程語言 正文
概要
在調用第三方 API 的時候, 基本都有訪問限速的限制條件. 第三方的 API 有多個的時候, 就不太好控制訪問速度, 常常會導致 HTTP 429(Too Many Requests) 然后就會有一段時間的禁止訪問.
為了應對這種限速的情況, 通過一個簡單的請求隊列來控制訪問的速度, 之后基本沒遇到過 HTTP 429 了.
實現思路
首先, 每個請求包裝成一個 RequestParam 的 struct, 其中包含請求的地址,類型,參數以及 response 的 channel.
發送請求的時候, 只要將 RequestParam 放入請求隊列中即可, 請求完成后, 將 response 放入對應的 channel 中.
整個代碼實現很簡單:
package util import ( "fmt" apiclient "gitee.com/wangyubin/gutils/api_client" "gitee.com/wangyubin/gutils/logger" ) // request 包含的內容 type RequestParam struct { Api string Method string JsonReq interface{} Resp chan []byte } // 請求隊列, 本質是一個channel type RequestQueue struct { Queue chan RequestParam } var queue *RequestQueue // 獲取隊列 func GetQueue() *RequestQueue { return queue } // 初始化隊列 func InitRequestQueue(size int) { queue = &RequestQueue{ Queue: make(chan RequestParam, size), } } // 將請求放入隊列 func (rq *RequestQueue) Enqueue(p RequestParam) { rq.Queue <- p } // 請求隊列服務, 一直等待接受和處理請求 func (rq *RequestQueue) Run() { lg := logger.GetLogger() for p := range rq.Queue { var resp []byte var err error switch p.Method { case "GET": resp, err = apiclient.GetJson(p.Api, p.JsonReq) case "POST": resp, err = apiclient.PostJson(p.Api, p.JsonReq) default: err = fmt.Errorf("Wrong type of METHOD(%s)\n", p.Method) } if err != nil { lg.Err(err).Msg("access api error: " + p.Api) continue } if p.Resp != nil { p.Resp <- resp close(p.Resp) } } lg.Info().Msg("request queue finished!") }
這里的請求是用了我自己封裝的 apiclient, 可以根據實際情況替換.
在我的應用場景里, 只要 api 順序訪問就不會出現 HTTP 429 了, 如果這樣覺得速度太快的的話, 可以嘗試在 Run() 函數中加入一些時間間隔.
func (rq *RequestQueue) Run() { lg := logger.GetLogger() for p := range rq.Queue { time.Sleep(1 * time.Second) // ... 省略的代碼 ... } lg.Info().Msg("request queue finished!") }
使用方法
使用很簡單, 首先啟動, 然后每個調用的地方將 RequestParam 放入隊列并等待 response 即可.
啟動隊列服務?
func main() { // init request queue and start queue service util.InitRequestQueue(100) queue := util.GetQueue() defer close(queue.Queue) go queue.Run() // 其他啟動代碼 }
使用隊列服務
func Request(param1 string, param2 int) error { api := "http://xxxx.com" api = fmt.Sprintf("%s?period=%s&size=%d", api, param1, param2) queue := util.GetQueue() param := util.RequestParam{ Api: api, Method: "GET", Resp: make(chan []byte, 1), } queue.Enqueue(param) var respData struct { Status string `json:"status"` Data []model.Data `json:"data"` } var err error for resp := range param.Resp { err = json.Unmarshal(resp, &respData) if err != nil { lg.Err(err).Msg("unmarshal json error") return err } } fmt.Println(respData) return err }
原文鏈接:https://www.cnblogs.com/wang_yb/p/13018901.html
相關推薦
- 2022-10-09 C#實現線性查找算法_C#教程
- 2022-02-07 virtualenvwrapper 解決安裝報錯,virtualenvwrapper 永久生效
- 2022-08-03 Python?權限控制模塊?Casbin_python
- 2023-04-04 Golang利用casbin實現權限驗證詳解_Golang
- 2022-05-05 C++繼承中的對象構造與析構和賦值重載詳解_C 語言
- 2022-12-22 React?Hooks?-?useContetx和useReducer的使用實例詳解_React
- 2023-02-10 android?原生安全音量配置邏輯設計詳解_Android
- 2023-01-28 GoLang?nil與interface的空指針深入分析_Golang
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支