Python并发请求下限制QPS(每秒查询率)的实现代码


Posted in Python onJune 05, 2020

  前两天有一个需求,需要访问某API服务器请求数据,该服务器限制了QPS=2(哈哈应该都知道是哪个服务器了吧_(:з」∠)_),因为QPS很小所以就使用阻塞式请求。后来开通了服务,QPS提高到了20,阻塞式请求满足不了这个QPS了,于是使用了GRequests来并发请求数据,但这里又遇到了一个问题:并发太快,服务器通过发送错误码拒绝了很多数据的响应,造成了资源的浪费。
  故在此记录以下几种 节流(Throttle) 方法:

  以下均假设有如下包和数据前提:

import grequests

urls = [
 "https://www.baidu.com",
 "https://www.google.com"
]
requests = [
 grequests.get(url)
 for url in urls
] * 1000

rate = 20 # 表示 20 请求/秒

time.sleep(1)

  这是最简单的方法,通过time.sleep(1)阻塞进程来控制每秒并发数量。用公式表达如下:Time=++time.sleep(1)Time = 请求准备时延 + 请求发送时延 + time.sleep(1)Time=请求准备时延+请求发送时延+time.sleep(1)   但是这种方法有一个较小的问题:不精确 。数据量越大,方差越大。

from time import sleep

req_groups = [
 requests[i: i+rate]
 for i in range(0, len(requests), rate)
]

ret = []
for req_group in req_groups:
 ret += grequests.map(req_group)
 sleep(1)

print(ret)

令牌桶(token bucket)方法

  这种方法较精确,可以确保误差不超过±1(当然前提是你的电脑和目标服务器都能承受的了高并发)。以下是耗时的公式表示:Time=++延Time = 请求准备时延 + 请求发送时延 + 令牌桶阻塞时延Time=请求准备时延+请求发送时延+令牌桶阻塞时延 1+延令牌桶阻塞时延 ≈ 1 - 请求准备时延 + 请求发送时延令牌桶阻塞时延≈1−请求准备时延+请求发送时延   这种方法当然也有一点缺陷,CPU看起来会很高(这是由于 while pass),尽管CPU真实使用率很低。

from time import time

class Throttle:
 def __init__(self, rate):
  self.rate = rate
  self.tokens = 0
  self.last = 0
 
 def consume(self, amount=1):
  now = time()
  
  if self.last == 0:
   self.last = now
  
  elapsed = now - self.last

  if int(elapsed * self.rate):
   self.tokens += int(elapsed * self.rate)
   self.last = now
  
  self.tokens = (
   self.rate
   if self.tokens > self.rate
   else self.tokens
  )
  
  if self.tokens >= amount:
   self.tokens -= amount
  else:
   amount = 0
  
  return amount

throttle = Throttle(rate)

req_groups = [
 requests[i: i+rate]
 for i in range(0, len(requests), rate)
]

ret = []
for req_group in req_groups:
 ret += grequests.map(req_group)
 while throttle.consume():
  pass # 阻塞

print(ret)

GRequests-Throttle

  这是一个使用令牌桶(token bucket)方法进行封装的GRequests修改版,使用方法很简单:
  首先安装grequests-throttle(清华镜像源更新较慢,推荐使用阿里镜像源)

pip install grequests-throttle
import grequests_throttle as gt

ret = gt.map(requests, rate=rate)
print(ret)

总结

  如果并发请求数量较小,可以考虑使用time.sleep(1)简单快捷;当并发请求数量较大时,使用令牌桶(token bucket)方法能最大化利用每一秒;如果不想写太多代码,可以使用GRequests-Throttle包进行请求流量控制。

到此这篇关于Python并发请求下限制QPS(每秒查询率)实现的文章就介绍到这了,更多相关Python并发请求下限制QPS(每秒查询率)实现内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
跟老齐学Python之从if开始语句的征程
Sep 14 Python
Python提示[Errno 32]Broken pipe导致线程crash错误解决方法
Nov 19 Python
Python实现八大排序算法
Aug 13 Python
python中子类继承父类的__init__方法实例
Dec 15 Python
python tensorflow基于cnn实现手写数字识别
Jan 01 Python
运动检测ViBe算法python实现代码
Jan 09 Python
Python实现的栈(Stack)
Jan 26 Python
python3获取两个日期之间所有日期,以及比较大小的实例
Apr 08 Python
500行代码使用python写个微信小游戏飞机大战游戏
Oct 16 Python
PHP基于phpqrcode类库生成二维码过程解析
May 28 Python
Python的控制结构之For、While、If循环问题
Jun 30 Python
教你用python控制安卓手机
May 13 Python
Python爬虫爬取百度搜索内容代码实例
Jun 05 #Python
python3读取autocad图形文件.py实例
Jun 05 #Python
Python实现加密接口测试方法步骤详解
Jun 05 #Python
基于python 将列表作为参数传入函数时的测试与理解
Jun 05 #Python
python 引用传递和值传递详解(实参,形参)
Jun 05 #Python
Python检测端口IP字符串是否合法
Jun 05 #Python
Python如何基于Tesseract实现识别文字功能
Jun 05 #Python
You might like
CakePHP去除默认显示的标题及图标的方法
2008/10/22 PHP
ThinkPHP登录功能的实现方法
2014/08/20 PHP
jquery 字符串切割函数substring的用法说明
2014/02/11 Javascript
浅析Node.js查找字符串功能
2014/09/03 Javascript
Javascript数据结构与算法之列表详解
2015/03/12 Javascript
JavaScript对象反射用法实例
2015/04/17 Javascript
Java遍历集合方法分析(实现原理、算法性能、适用场合)
2016/04/25 Javascript
Javascript点击其他任意地方隐藏关闭DIV实例
2016/06/21 Javascript
jquery中live()方法和bind()方法区别分析
2016/06/23 Javascript
javascript中this关键字详解
2016/12/12 Javascript
AngularJS指令与控制器之间的交互功能示例
2016/12/14 Javascript
JS图片轮播与索引变色功能实例详解
2017/07/06 Javascript
jquery 实现拖动文件上传加载进度条功能
2018/03/18 jQuery
详解node Async/Await 更好的异步编程解决方案
2018/05/10 Javascript
初探Vue3.0 中的一大亮点Proxy的使用
2018/12/06 Javascript
微信小程序在其他页面监听globalData中值的变化
2019/07/15 Javascript
Python用Bottle轻量级框架进行Web开发
2016/06/08 Python
python实现随机梯度下降(SGD)
2020/03/24 Python
Python异常处理操作实例详解
2018/05/10 Python
对sklearn的使用之数据集的拆分与训练详解(python3.6)
2018/12/14 Python
python中自带的三个装饰器的实现
2019/11/08 Python
python实现扫雷小游戏
2020/04/24 Python
Django模板标签{% for %}循环,获取制定条数据实例
2020/05/14 Python
如何通过命令行进入python
2020/07/06 Python
PyCharm最新激活码(2020/10/27全网最新)
2020/10/27 Python
用pushplus+python监控亚马逊到货动态推送微信
2021/01/29 Python
UML设计模式笔试题
2014/06/07 面试题
灵泰克Java笔试题
2016/01/09 面试题
增员口号大全
2014/06/18 职场文书
2014年大学生预备党员思想汇报1000字
2014/09/13 职场文书
查摆问题自查报告范文
2014/10/13 职场文书
英文版辞职信
2015/02/28 职场文书
学校重阳节活动总结
2015/03/24 职场文书
人与自然的观后感
2015/06/18 职场文书
2016年中秋祝酒词
2015/11/26 职场文书
详解Redis的三种常用的缓存读写策略步骤
2022/05/06 Redis