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实现文件分组复制到不同目录的例子
Jun 04 Python
python避免死锁方法实例分析
Jun 04 Python
使用python 爬虫抓站的一些技巧总结
Jan 10 Python
python+matplotlib实现鼠标移动三角形高亮及索引显示
Jan 15 Python
对pandas的行列名更改与数据选择详解
Nov 12 Python
Python发送邮件功能示例【使用QQ邮箱】
Dec 04 Python
执行Django数据迁移时报 1091错误及解决方法
Oct 14 Python
python GUI库图形界面开发之PyQt5窗口布局控件QStackedWidget详细使用方法
Feb 27 Python
python查看矩阵的行列号以及维数方式
May 22 Python
Django REST Swagger实现指定api参数
Jul 07 Python
详解anaconda安装步骤
Nov 23 Python
python实现简单的名片管理系统
Apr 26 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开发框架总结收藏
2008/04/24 PHP
PHP数据库万能引擎类adodb配置使用以及实例集锦
2014/06/12 PHP
php实现简单的MVC框架实例
2015/09/23 PHP
基于命令行执行带参数的php脚本并取得参数的方法
2016/01/25 PHP
3种方法轻松处理php开发中emoji表情的问题
2016/07/18 PHP
Ubuntu中支持PHP5与PHP7双版本的简单实现
2018/08/19 PHP
jquery下利用jsonp跨域访问实现方法
2010/07/29 Javascript
JS弹出对话框返回值代码(asp.net后台)
2010/12/28 Javascript
使用documentElement正确取得当前可见区域的大小
2014/07/25 Javascript
用js代码和插件实现wordpress雪花飘落效果的四种方法
2014/12/15 Javascript
javascript 事件处理示例分享
2014/12/31 Javascript
jQuery右侧选项卡焦点图片轮播特效代码分享
2015/09/05 Javascript
js实现的鼠标滚轮滚动切换页面效果(类似360默认页面滚动切换效果)
2016/01/27 Javascript
Bootstrap table两种分页示例
2016/12/23 Javascript
JavaScript 获取元素在父节点中的下标(推荐)
2017/06/28 Javascript
原生JS实现Ajax跨域请求flask响应内容
2017/10/24 Javascript
基于vue开发的在线付费课程应用过程
2018/01/25 Javascript
浅谈vue首屏加载优化
2018/06/28 Javascript
使用Vuex解决Vue中的身份验证问题
2018/09/28 Javascript
vue.js自定义组件实现v-model双向数据绑定的示例代码
2020/01/08 Javascript
基于Cesium绘制抛物弧线
2020/11/18 Javascript
[01:44]Ti10举办地公布
2019/08/25 DOTA
Python下singleton模式的实现方法
2014/07/16 Python
Python同时向控制台和文件输出日志logging的方法
2015/05/26 Python
python中的编码知识整理汇总
2016/01/26 Python
Python基于time模块求程序运行时间的方法
2017/09/18 Python
解决Shell执行python文件,传参空格引起的问题
2018/10/30 Python
Django Rest framework三种分页方式详解
2019/07/26 Python
解决python 文本过滤和清理问题
2019/08/28 Python
Python3如何在服务器打印资产信息
2020/08/27 Python
HTML5之HTML元素扩展(上)—新增加的元素及使用概述
2013/01/31 HTML / CSS
美国顶级品牌男士大码服装店:DXL
2017/08/30 全球购物
Geekbuying波兰:购买中国电子产品
2019/10/20 全球购物
大客户销售经理职责
2013/12/04 职场文书
学习型党组织心得体会
2014/09/12 职场文书
人口与计划生育责任书
2015/05/09 职场文书