golang API 请求队列
概要
在调用第三方 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 请求队列的更多相关文章
- ASP.Net的工作线程与请求队列
当 ASP.NET 接收针对页的请求时,它从线程池中提取一个线程并将请求分配给该线程. 一个普通的(或同步的)页在该请求期间保留线程,从而防止该线程用于处理其他请求.如果一个同步请求成为 I/O bo ...
- 在Android中,使用Kotlin的 API请求简易方法
原文标题:API request in Android the easy way using Kotlin 原文链接:http://antonioleiva.com/api-request-kotli ...
- 编写简单的ramdisk(有请求队列)
前言 前面用无请求队列实现的ramdisk的驱动程序虽然申请了请求队列,但实际上没用上,因为ramdisk不像实际的磁盘访问速度慢需要缓存,ramdisk之间使用内存空间,所以就没用请求队列了.本文将 ...
- 编写简单的ramdisk(无请求队列)
最近在研究块设备驱动的编写,看了赵磊大牛的<写一个块设备驱动>,受益匪浅,虽然能看懂里面说的,但动手写写代码还是能加深理解的,下面实现的ramdisk写的很简单,如果有错误,欢迎大牛们指正 ...
- vue项目实践-添加axios封装api请求
安装 axios npm install axios --save 创建实例 (utils/fetch.js) axios 默认提交格式为:application/json 可使用 qs 模块(需要安 ...
- laravel5.7 前后端分离开发 实现基于API请求的token认证
最近在学习前后端分离开发,发现 在laravel中实现前后台分离是无法无法使用 CSRF Token 认证的.因为 web 请求的用户认证是通过Session和客户端Cookie的实现的,而前后端分离 ...
- 微信小程序开发——使用mock数据模拟api请求
前言: 微信小程序开发中,后端提供了接口设计文档,前端可以先mock数据模拟api请求进行开发调试,而且可以根据需要设计mock文件的格式和内容,这样在后端接口开发完成之前,前端可以最大限度的完成前端 ...
- [Postman]排除API请求(9)
可能存在API无法运行或出现意外行为的情况.如果您没有收到任何回复,邮递员将显示有关连接服务器时出错的消息. 有关错误可能原因的更多详细信息,请打开Postman Console.它有关于故障的详细信 ...
- Android开发 - Retrofit 2 使用自签名的HTTPS证书进行API请求
为了确保数据传输的安全,现在越来越多的应用使用Https的方式来进行数据传输,使用https有很多有点,比如: HTTPS协议是由SSL+HTTP协议构建的可进行加密传输.身份认证的网络协议,要比ht ...
随机推荐
- Windows下安装nvm管理多个nodejs版本
平常在工作中难免会有node版本的要求,下面介绍一种利用nvm工具管理多个node版本的方法 下载安装 Github: Download nvm-windows --- nvm-setup.zip 程 ...
- Git 实用操作:重写 Commit 历史
当我们修改完代码,提交了一个 commit,然后发现改错了,怎么修正?下面分两种情况来讨论:修正最近一次提交,和修正历史多个提交. 修正最近一次提交 如果发现刚刚提交的内容有错误,当场再修改一下再提交 ...
- Zabbix 5.0 LTS版本的安装小结
Zabbix 5.0 LTS版本的安装小结 1:准备Zabbix的服务器. 这里可能需要一台或多台服务器,视需求和资源而定.也可以将Zabbix_Server.MySQL.Zabbix Web等安 ...
- Q20200511-01 翻转字符串
需求:做一函数将字符串倒转过来 程序: package test4; public class Reverse { public static String reverse(String origin ...
- Cassandra使用的各种策略
1. 背景介绍 Cassandra 使用分布式哈希表(DHT)来确定存储某一个数据对象的节点.在 DHT 里面,负责存储的节点以及数据对象都被分配一个 token.token 只能在一定的范围内取值, ...
- Spring IoC 到底是什么
前言 「上一篇文章」我们对 Spring 有了初步的认识,而 Spring 全家桶中几乎所有组件都是依赖于 IoC 的. 刚开始听到 IoC,会觉得特别高大上,但其实掰开了很简单. 跟着我的脚步,一文 ...
- 【盗墓笔记】图解使用fat-aar方式在AndroidStudio中打包嵌套第三方aar的aar
将一些项目中的一些独立功能打包成aar,不仅能于项目解耦,还能够提供给其它项目使用相同的功能,可谓是为项目开发带来了很大的便利.最近第一次做sdk,碰到一些问题,花了不少时间才解决,所以这里做一下简单 ...
- jzoj 3431. 【GDOI2014模拟】网格
Description 某城市的街道呈网格状,左下角坐标为A(0, 0),右上角坐标为B(n, m),其中n >= m.现在从A(0, 0)点出发,只能沿着街道向正右方或者正上方行走,且不能经过 ...
- jzoj 3567. 【GDKOI2014】石油储备计划
Problem Description Input Output 对于每组数据,输出一个整数,表示达到"平衡"状态所需的最小代价. Data Constraint 对于20%的数据 ...
- 工具-Typora常用语法()+自己总结
工具-Typora常用语法 Markdown(MD)作为目前互联网写作相当流行的一种文档撰写语言格式,深受互联网编辑者的喜爱,由此周边一些基于MD的编辑工具也随之油然而生. 作为一款免费的MD编辑器: ...