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进阶之递归函数的用法及其示例
Jan 31 Python
Python3.4实现远程控制电脑开关机
Feb 22 Python
python之从文件读取数据到list的实例讲解
Apr 19 Python
如何使用Python的Requests包实现模拟登陆
Apr 27 Python
在Mac上删除自己安装的Python方法
Oct 29 Python
Python3.5常见内置方法参数用法实例详解
Apr 29 Python
Pandas0.25来了千万别错过这10大好用的新功能
Aug 07 Python
使用celery和Django处理异步任务的流程分析
Feb 19 Python
python的Jenkins接口调用方式
May 12 Python
Python classmethod装饰器原理及用法解析
Oct 17 Python
python中绕过反爬虫的方法总结
Nov 25 Python
python使用tkinter实现透明窗体上绘制随机出现的小球(实例代码)
May 17 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 字符转义 注意事项
2009/05/27 PHP
浅析get与post的一些特殊情况
2014/07/28 PHP
php生成年月日下载列表的方法
2015/04/24 PHP
分享五个PHP7性能优化提升技巧
2015/12/07 PHP
php读取出一个文件夹及其子文件夹下所有文件的方法示例
2017/06/15 PHP
PHP中ltrim()函数的用法与实例讲解
2019/03/28 PHP
js动态为代码着色显示行号
2013/05/29 Javascript
MultiSelect左右选择控件的设计与实现介绍
2013/06/08 Javascript
JS+CSS实现实用的单击输入框弹出选择框的方法
2015/02/28 Javascript
javascript清空table表格的方法
2015/05/14 Javascript
分享12个非常实用的JavaScript小技巧
2016/05/11 Javascript
AngularJS入门示例之Hello World详解
2017/01/04 Javascript
浅谈angularjs $http提交数据探索
2017/01/20 Javascript
微信公众号菜单配置微信小程序实例详解
2017/03/31 Javascript
Vuejs实现带样式的单文件组件新方法
2017/05/02 Javascript
Vue.js的动态组件模板的实现
2018/11/26 Javascript
一百行JS代码实现一个校验工具
2019/04/30 Javascript
在Vue项目中使用Typescript的实现
2019/12/19 Javascript
vue-cli3 取消eslint校验代码的解决办法
2020/01/16 Javascript
基于JS实现视频上传显示进度条
2020/05/12 Javascript
[02:23]DOTA2英雄基础教程 幻影长矛手
2013/12/09 DOTA
[53:49]LGD vs Fnatic 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
Python THREADING模块中的JOIN()方法深入理解
2015/02/18 Python
归纳整理Python中的控制流语句的知识点
2015/04/14 Python
Django imgareaselect手动剪切头像实现方法
2015/05/26 Python
Python 3.8正式发布重要新功能一览
2019/10/17 Python
基于jupyter代码无法在pycharm中运行的解决方法
2020/04/21 Python
PyQT5速成教程之Qt Designer介绍与入门
2020/11/02 Python
《孔子游春》教学反思
2014/02/25 职场文书
会员活动策划方案
2014/08/19 职场文书
2015大学生实训报告
2014/11/05 职场文书
门市房租房协议书
2014/12/04 职场文书
升学宴家长致辞
2015/07/27 职场文书
2016年先进班集体事迹材料
2016/02/26 职场文书
如何用JavaScript检测当前浏览器是无头浏览器
2021/04/27 Javascript
使用kubeadm命令行工具创建kubernetes集群
2022/03/31 Servers