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中ConfigParse模块的用法
Sep 29 Python
Python实现简单HTML表格解析的方法
Jun 15 Python
深入理解NumPy简明教程---数组1
Dec 17 Python
Python中defaultdict与lambda表达式用法实例小结
Apr 09 Python
Python实现曲线拟合操作示例【基于numpy,scipy,matplotlib库】
Jul 12 Python
Python快速转换numpy数组中Nan和Inf的方法实例说明
Feb 21 Python
如何不用安装python就能在.NET里调用Python库
Jul 12 Python
多版本python的pip 升级后, pip2 pip3 与python版本失配解决方法
Sep 11 Python
Python容器使用的5个技巧和2个误区总结
Sep 26 Python
关于tensorflow的几种参数初始化方法小结
Jan 04 Python
Pandas实现DataFrame的简单运算、统计与排序
Mar 31 Python
Python实现自动玩连连看的脚本分享
Apr 04 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
PHP 开源AJAX框架14种
2009/08/24 PHP
从手册去理解分析PHP session机制
2011/07/17 PHP
ThinkPHP空模块和空操作详解
2014/06/30 PHP
PHP实现通过中文字符比率来判断垃圾评论的方法
2014/10/20 PHP
PHP asXML()函数讲解
2019/02/03 PHP
关于laravel 日志写入失败问题汇总
2019/10/17 PHP
javascript的对话框详解与参数
2007/03/08 Javascript
js实现数字每三位加逗号的方法
2015/02/05 Javascript
jquery+javascript编写国籍控件
2015/02/12 Javascript
jQuery向后台传入json格式数据的方法
2015/02/13 Javascript
js实现彩色条纹滚动条效果
2017/03/15 Javascript
完美解决axios在ie下的兼容性问题
2018/03/05 Javascript
JS 实现微信扫一扫功能
2018/09/14 Javascript
elementui更改el-dialog关闭按钮的图标d的示例代码
2020/08/04 Javascript
Python和perl实现批量对目录下电子书文件重命名的代码分享
2014/11/21 Python
python每隔N秒运行指定函数的方法
2015/03/16 Python
Python中pygame安装方法图文详解
2015/11/11 Python
Python脚本实现自动发带图的微博
2016/04/27 Python
对变量赋值的理解--Pyton中让两个值互换的实现方法
2017/11/29 Python
利用python将xml文件解析成html文件的实现方法
2017/12/22 Python
简单实现python收发邮件功能
2018/01/05 Python
Python获取CPU、内存使用率以及网络使用状态代码
2018/02/08 Python
python3人脸识别的两种方法
2019/04/25 Python
python 一篇文章搞懂装饰器所有用法(建议收藏)
2019/08/23 Python
浅谈在JupyterNotebook下导入自己的模块的问题
2020/04/16 Python
django model 条件过滤 queryset.filter(**condtions)用法详解
2020/05/20 Python
python与pycharm有何区别
2020/07/01 Python
python 获取域名到期时间的方法步骤
2021/02/10 Python
css3如何绘制一个圆圆的loading转圈动画
2018/01/09 HTML / CSS
手机银行营销方案
2014/03/14 职场文书
保护水资源的标语
2014/06/17 职场文书
质量整改报告范文
2014/11/08 职场文书
写给父母的感谢信
2015/01/22 职场文书
2016北大自主招生自荐信模板
2016/01/28 职场文书
Java后端 Dubbo retries 超时重试机制的解决方案
2022/04/14 Java/Android
nginx容器方式反向代理实战
2022/04/18 Servers