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实现mysql的单引号字符串过滤方法
Nov 14 Python
Python使用Redis实现作业调度系统(超简单)
Mar 22 Python
使用Python的Flask框架表单插件Flask-WTF实现Web登录验证
Jul 12 Python
python 将json数据提取转化为txt的方法
Oct 26 Python
python 根据时间来生成唯一的字符串方法
Jan 14 Python
解决python文件双击运行秒退的问题
Jun 24 Python
详解Python time库的使用
Oct 10 Python
Python matplotlib以日期为x轴作图代码实例
Nov 22 Python
python @propert装饰器使用方法原理解析
Dec 25 Python
pycharm开发一个简单界面和通用mvc模板(操作方法图解)
May 27 Python
python爬取企查查企业信息之selenium自动模拟登录企查查
Apr 08 Python
python基础之类属性和实例属性
Oct 24 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 面向对象之成员方法详解
2013/05/04 PHP
PHP循环输出指定目录下的所有文件和文件夹路径例子(简单实用)
2014/05/10 PHP
PHP函数实现分页含文本分页和数字分页
2014/10/23 PHP
jQuery 全选效果实现代码
2009/03/23 Javascript
JavaScript中对象属性的添加和删除示例
2014/05/12 Javascript
js实现仿Windows风格选项卡和按钮效果实例
2015/05/13 Javascript
分享jQuery网页元素拖拽插件
2020/12/01 Javascript
利用JS实现页面删除并重新排序功能
2016/12/09 Javascript
Bootstrap CSS组件之按钮组(btn-group)
2016/12/17 Javascript
Easyui笔记2:实现datagrid多行删除的示例代码
2017/01/14 Javascript
JS生成一维码(条形码)功能示例
2017/01/19 Javascript
JavaScript数据结构之链表的实现
2017/03/19 Javascript
Flask中获取小程序Request数据的两种方法
2017/05/12 Javascript
Angular2使用vscode断点调试ts文件的方法
2017/12/13 Javascript
Angular17之Angular自定义指令详解
2018/01/21 Javascript
在vue项目中,使用axios跨域处理
2018/03/07 Javascript
[03:02]安得倚天剑,跨海斩长鲸——中国军团出征DOTA2国际邀请赛
2018/08/14 DOTA
Python之Scrapy爬虫框架安装及使用详解
2017/11/16 Python
python3使用scrapy生成csv文件代码示例
2017/12/28 Python
python中的字符串内部换行方法
2018/07/19 Python
Python字符串的全排列算法实例详解
2019/01/07 Python
python使用selenium登录QQ邮箱(附带滑动解锁)
2019/01/23 Python
python正则表达式匹配IP代码实例
2019/12/28 Python
python利用JMeter测试Tornado的多线程
2020/01/12 Python
django models里数据表插入数据id自增操作
2020/07/15 Python
高中毕业生自我鉴定范文
2013/09/26 职场文书
最新的互联网创业计划书
2014/01/10 职场文书
暑期学习心得体会
2014/09/02 职场文书
2014年小学班主任工作总结
2014/11/08 职场文书
汽车转让协议书
2015/01/29 职场文书
银行求职信范文怎么写
2015/03/20 职场文书
教师旷工检讨书
2015/08/15 职场文书
《将心比心》教学反思
2016/02/23 职场文书
IDEA 链接Mysql数据库并执行查询操作的完整代码
2021/05/20 MySQL
mysq启动失败问题及场景分析
2021/07/15 MySQL
JavaScript小技巧带你提升你的代码技能
2021/09/15 Javascript