登录
首页 >  Golang >  Go教程

golangAPI请求队列的实现

来源:脚本之家

时间:2023-01-24 18:15:26 489浏览 收藏

本篇文章主要是结合我之前面试的各种经历和实战开发中遇到的问题解决经验整理的,希望这篇《golangAPI请求队列的实现》对你有很大帮助!欢迎收藏,分享给更多的需要的朋友学习~

概要

在调用第三方 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 

这里的请求是用了我自己封装的 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
  }

今天关于《golangAPI请求队列的实现》的内容介绍就到此结束,如果有什么疑问或者建议,可以在golang学习网公众号下多多回复交流;文中若有不正之处,也希望回复留言以告知!

声明:本文转载于:脚本之家 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>
评论列表