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 过滤字符串的技巧,map与itertools.imap
Sep 06 Python
python list中append()与extend()用法分享
Mar 24 Python
python中__call__方法示例分析
Oct 11 Python
玩转python selenium鼠标键盘操作(ActionChains)
Apr 12 Python
apache部署python程序出现503错误的解决方法
Jul 24 Python
Python文件和流(实例讲解)
Sep 12 Python
浅谈Python的条件判断语句if/else语句
Mar 21 Python
Python3 实现爬取网站下所有URL方式
Jan 16 Python
python实现凯撒密码、凯撒加解密算法
Jun 11 Python
pytorch  网络参数 weight bias 初始化详解
Jun 24 Python
Python机器学习工具scikit-learn的使用笔记
Jan 28 Python
Python实现简单得递归下降Parser
May 02 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异常处理定义与使用方法分析
2017/07/25 PHP
php实现微信公众号创建自定义菜单功能的实例代码
2019/06/11 PHP
脚本吧 - 幻宇工作室用到js,超强推荐share.js
2006/12/23 Javascript
AutoSave/自动存储功能实现
2007/03/24 Javascript
javascript之函数直接量(function(){})()
2007/06/29 Javascript
基于Jquery的淡入淡出的特效基础练习
2010/12/13 Javascript
JS trim去空格的最佳实践
2011/10/30 Javascript
js判断变量是否未定义的代码
2020/03/28 Javascript
使用js画图之画切线
2015/01/12 Javascript
Node.js中的流(Stream)介绍
2015/03/30 Javascript
javascript实现的图片切割多块效果实例
2015/05/07 Javascript
jQuery循环遍历子节点并获取值的方法
2016/04/14 Javascript
jquery.cookie.js实现用户登录保存密码功能的方法
2016/04/15 Javascript
javascript简单实现等比例缩小图片的方法
2016/07/27 Javascript
AngularJS应用开发思维之依赖注入3
2016/08/19 Javascript
详解js的事件代理(委托)
2016/12/22 Javascript
详解Vue 普通对象数据更新与 file 对象数据更新
2017/04/26 Javascript
详解vue2 $watch要注意的问题
2017/09/08 Javascript
微信小程序实现音乐播放页面布局
2020/12/11 Javascript
Python实现的RSS阅读器实例
2015/07/25 Python
django实现用户登陆功能详解
2017/12/11 Python
Python Pandas中根据列的值选取多行数据
2019/07/08 Python
python网络编程之五子棋游戏
2020/05/14 Python
Python如何给函数库增加日志功能
2020/08/04 Python
基于html5 DeviceOrientation 实现微信摇一摇功能
2015/09/25 HTML / CSS
英国家喻户晓的高街品牌:River Island
2017/11/28 全球购物
kfc实习自我鉴定
2013/12/14 职场文书
中学家长会邀请函
2014/02/03 职场文书
5.12护士节演讲稿
2014/04/30 职场文书
给校长的建议书400字
2014/05/15 职场文书
医疗专业毕业生求职信
2014/08/28 职场文书
2015年助残日活动总结
2015/03/27 职场文书
禁毒主题班会教案
2015/08/14 职场文书
利用前端HTML+CSS+JS开发简单的TODOLIST功能(记事本)
2021/04/13 Javascript
asyncio异步编程之Task对象详解
2022/03/13 Python
mysql全面解析json/数组
2022/07/07 MySQL