码迷,mamicode.com
首页 > Windows程序 > 详细

golang API 请求队列

时间:2020-05-31 15:57:24      阅读:88      评论:0      收藏:0      [点我收藏+]

标签:时间间隔   xxxx   rsh   start   byte   mod   logger   def   根据   

概要

在调用第三方 API 的时候, 基本都有访问限速的限制条件. 第三方的 API 有多个的时候, 就不太好控制访问速度, 常常会导致 HTTP 429(Too Many Requests) 然后就会有一段时间的禁止访问.

为了应对这种限速的情况, 通过一个简单的请求队列来控制访问的速度, 之后基本没遇到过 HTTP 429 了.

实现思路

首先, 每个请求包装成一个 RequestParam 的 struct, 其中包含请求的地址,类型,参数以及 response 的 channel.

发送请求的时候, 只要将 RequestParam 放入请求队列中即可, 请求完成后, 将 response 放入对应的 channel 中.

整个代码实现很简单:

 1  package util
 2  
 3  import (
 4    "fmt"
 5  
 6    apiclient "gitee.com/wangyubin/gutils/api_client"
 7    "gitee.com/wangyubin/gutils/logger"
 8  )
 9  
10  // request 包含的内容
11  type RequestParam struct {
12    Api     string
13    Method  string
14    JsonReq interface{}
15    Resp    chan []byte
16  }
17  
18  // 请求队列, 本质是一个channel
19  type RequestQueue struct {
20    Queue chan RequestParam
21  }
22  
23  var queue *RequestQueue
24  
25  // 获取队列
26  func GetQueue() *RequestQueue {
27    return queue
28  }
29  
30  // 初始化队列
31  func InitRequestQueue(size int) {
32    queue = &RequestQueue{
33      Queue: make(chan RequestParam, size),
34    }
35  }
36  
37  // 将请求放入队列
38  func (rq *RequestQueue) Enqueue(p RequestParam) {
39    rq.Queue <- p
40  }
41  
42  // 请求队列服务, 一直等待接受和处理请求
43  func (rq *RequestQueue) Run() {
44    lg := logger.GetLogger()
45    for p := range rq.Queue {
46      var resp []byte
47      var err error
48      switch p.Method {
49      case "GET":
50        resp, err = apiclient.GetJson(p.Api, p.JsonReq)
51      case "POST":
52        resp, err = apiclient.PostJson(p.Api, p.JsonReq)
53      default:
54        err = fmt.Errorf("Wrong type of METHOD(%s)\n", p.Method)
55      }
56  
57      if err != nil {
58        lg.Err(err).Msg("access api error: " + p.Api)
59        continue
60      }
61      if p.Resp != nil {
62        p.Resp <- resp
63        close(p.Resp)
64      }
65    }
66  
67    lg.Info().Msg("request queue finished!")
68  }

这里的请求是用了我自己封装的 apiclient, 可以根据实际情况替换.

在我的应用场景里, 只要 api 顺序访问就不会出现 HTTP 429 了, 如果这样觉得速度太快的的话, 可以尝试在 Run() 函数中加入一些时间间隔.

1  func (rq *RequestQueue) Run() {
2    lg := logger.GetLogger()
3    for p := range rq.Queue {
4       time.Sleep(1 * time.Second)
5       // ... 省略的代码 ...
6    }
7  
8    lg.Info().Msg("request queue finished!")
9  }

使用方法

使用很简单, 首先启动, 然后每个调用的地方将 RequestParam 放入队列并等待 response 即可.

启动队列服务

1  func main() {
2      // init request queue and start queue service
3      util.InitRequestQueue(100)
4      queue := util.GetQueue()
5      defer close(queue.Queue)
6      go queue.Run()
7  
8      // 其他启动代码
9  }

使用队列服务

 1  func Request(param1 string, param2 int) error {
 2   api := "http://xxxx.com"
 3   api = fmt.Sprintf("%s?period=%s&size=%d", api, param1, param2)
 4  
 5   queue := util.GetQueue()
 6   param := util.RequestParam{
 7     Api:    api,
 8     Method: "GET",
 9     Resp:   make(chan []byte, 1),
10   }
11   queue.Enqueue(param)
12  
13   var respData struct {
14     Status string       `json:"status"`
15     Data   []model.Data `json:"data"`
16   }
17   var err error
18   for resp := range param.Resp {
19     err = json.Unmarshal(resp, &respData)
20     if err != nil {
21       lg.Err(err).Msg("unmarshal json error")
22       return err
23     }
24   }
25  
26   fmt.Println(respData) 
27   return  err
28  }

golang API 请求队列

标签:时间间隔   xxxx   rsh   start   byte   mod   logger   def   根据   

原文地址:https://www.cnblogs.com/wang_yb/p/13018901.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!