使用Python的Treq on Twisted来进行HTTP压力测试


Posted in Python onApril 16, 2015

从事API相关的工作很有挑战性,在高峰期保持系统的稳定及健壮性就是其中之一,这也是我们在Mailgun做很多压力测试的原因。

这么久以来,我们已经尝试了很多种方法,从简单的ApacheBench到复杂些的自定义测试套。但是本贴讲述的,是一种使用python进行“快速粗糙”却非常灵活的压力测试的方法。
使用python写HTTP客户端的时候,我们都很喜欢用 Requests library。这也是我们向我们的API用户们推荐的。Requests 很强大,但有一个缺点,它是一个模块化的每线程一个调用的东西,很难或者说不可能用它来快速的产生成千上万级别的请求。
Treq on Twisted简介

为解决这个问题我们引入了Treq (Github库)。Treq是一个HTTP客户端库,受Requests影响,但是它运行在Twisted上,具有Twisted典型的强大能力:处理网络I/O时它是异步且高度并发的方式。

Treq并不仅仅限于压力测试:它是写高并发HTTP客户端的好工具,比如网页抓取。Treq很优雅、易于使用且强大。这是一个例子:

>>> from treq import get
  
 >>> def done(response):
 ...   print response.code
 ...   reactor.stop()
  
 >>> get("http://www.github.com").addCallback(done)
  
 >>> from twisted.internet import reactor
 200

简单的测试脚本
如下是一个使用Treq的简单脚本,用最大可能量的请求来对单一URL进行轰炸。

#!/usr/bin/env python
 from twisted.internet import epollreactor
 epollreactor.install()
  
 from twisted.internet import reactor, task
 from twisted.web.client import HTTPConnectionPool
 import treq
 import random
 from datetime import datetime
  
 req_generated = 0
 req_made = 0
 req_done = 0
  
 cooperator = task.Cooperator()
  
 pool = HTTPConnectionPool(reactor)
  
 def counter():
   '''This function gets called once a second and prints the progress at one
   second intervals.
   '''
   print("Requests: {} generated; {} made; {} done".format(
       req_generated, req_made, req_done))
   # reset the counters and reschedule ourselves
   req_generated = req_made = req_done = 0
   reactor.callLater(1, counter)
  
 def body_received(body):
   global req_done
   req_done += 1
  
 def request_done(response):
   global req_made
   deferred = treq.json_content(response)
   req_made += 1
   deferred.addCallback(body_received)
   deferred.addErrback(lambda x: None) # ignore errors
   return deferred
  
 def request():
   deferred = treq.post('http://api.host/v2/loadtest/messages',
              auth=('api', 'api-key'),
              data={'from': 'Loadtest <test@example.com>',
                 'to': 'to@example.org',
                'subject': "test"},
             pool=pool)
   deferred.addCallback(request_done)
   return deferred
  
 def requests_generator():
   global req_generated
   while True:
     deferred = request()
     req_generated += 1
     # do not yield deferred here so cooperator won't pause until
     # response is received
     yield None
  
 if __name__ == '__main__':
   # make cooperator work on spawning requests
   cooperator.cooperate(requests_generator())
  
   # run the counter that will be reporting sending speed once a second
   reactor.callLater(1, counter)
  
   # run the reactor
   reactor.run()

输出结果:

2013-04-25 09:30 Requests: 327 generated; 153 sent; 153 received
 2013-04-25 09:30 Requests: 306 generated; 156 sent; 156 received
 2013-04-25 09:30 Requests: 318 generated; 184 sent; 154 received

“Generated”类的数字代表被Twisted反应器准备好但是还没有发送的请求。这个脚本为了简洁性忽略了所有错误处理。为它添加超时状态的信息就留给读者作为一个练习。

这个脚本可以当做是一个起始点,你可以通过拓展改进它来自定义特定应用下的处理逻辑。建议你在改进的时候用collections.Counter 来替代丑陋的全局变量。这个脚本运行在单线程上,想通过一台机器压榨出最大量的请求的话,你可以用类似 mulitprocessing 的技术手段。

愿你乐在压力测试!

Python 相关文章推荐
在python的WEB框架Flask中使用多个配置文件的解决方法
Apr 18 Python
Python中的特殊语法:filter、map、reduce、lambda介绍
Apr 14 Python
python 3.6 tkinter+urllib+json实现火车车次信息查询功能
Dec 20 Python
Python实现字典按照value进行排序的方法分析
Dec 23 Python
对Python中class和instance以及self的用法详解
Jun 26 Python
扩展Django admin的list_filter()可使用范围方法
Aug 21 Python
Python使用scipy模块实现一维卷积运算示例
Sep 05 Python
Python爬虫实现使用beautifulSoup4爬取名言网功能案例
Sep 15 Python
python 类之间的参数传递方式
Dec 20 Python
python GUI库图形界面开发之PyQt5多线程中信号与槽的详细使用方法与实例
Mar 08 Python
python 使用while循环输出*组成的菱形实例
Apr 12 Python
Keras loss函数剖析
Jul 06 Python
Python3中多线程编程的队列运作示例
Apr 16 #Python
使用Python脚本操作MongoDB的教程
Apr 16 #Python
使用Python中的greenlet包实现并发编程的入门教程
Apr 16 #Python
利用Python的Twisted框架实现webshell密码扫描器的教程
Apr 16 #Python
使用Python的Twisted框架实现一个简单的服务器
Apr 16 #Python
使用Python的Twisted框架编写简单的网络客户端
Apr 16 #Python
从Python的源码浅要剖析Python的内存管理
Apr 16 #Python
You might like
PHP新手上路(十三)
2006/10/09 PHP
PHP实现对文本数据库的常用操作方法实例演示
2014/07/04 PHP
php自定义urlencode,urldecode函数实例
2015/03/24 PHP
用javascript自动显示最后更新时间
2007/03/15 Javascript
jquery中的sortable排序之后的保存状态的解决方法
2010/01/28 Javascript
解决jquery的datepicker的本地化以及Today问题
2012/05/23 Javascript
javascript打印输出json实例
2013/11/11 Javascript
元素未显示设置width/height时IE中使用currentStyle获取为auto
2014/05/04 Javascript
JavaScript实现将xml转换成html table表格的方法
2015/04/17 Javascript
javascript数组去重的六种方法汇总
2015/08/16 Javascript
Javascript实现跑马灯效果的简单实例
2016/05/31 Javascript
jQuery Select下拉框操作小结(推荐)
2016/07/22 Javascript
jquery判断对象是否为空并遍历对象的简单实例
2016/07/26 Javascript
简单的js计算器实现
2016/10/26 Javascript
微信小程序 使用picker封装省市区三级联动实例代码
2016/10/28 Javascript
JS中用三种方式实现导航菜单中的二级下拉菜单
2016/10/31 Javascript
vue.js指令v-for使用及索引获取
2016/11/03 Javascript
利用CSS、JavaScript及Ajax实现图片预加载的方法
2016/11/29 Javascript
微信小程序侧边栏滑动特效(左右滑动)
2017/01/23 Javascript
Bootstrap表单控件学习使用
2017/03/07 Javascript
vue-自定义组件传值的实例讲解
2018/09/18 Javascript
详解微信小程序用定时器实现倒计时效果
2019/04/30 Javascript
Node.js API详解之 module模块用法实例分析
2020/05/13 Javascript
解决vue初始化项目一直停在downloading template的问题
2020/11/09 Javascript
Python使用xlrd模块操作Excel数据导入的方法
2015/05/26 Python
win7上python2.7连接mysql数据库的方法
2017/01/14 Python
python爬虫入门教程--优雅的HTTP库requests(二)
2017/05/25 Python
python之pandas用法大全
2018/03/13 Python
对python xlrd读取datetime类型数据的方法详解
2018/12/26 Python
Python中super函数用法实例分析
2019/03/18 Python
Pandas+Matplotlib 箱式图异常值分析示例
2019/12/09 Python
ZINVO手表官网:男士和女士手表
2019/03/10 全球购物
高中语文教学反思
2014/01/16 职场文书
《千年梦圆在今朝》教学反思
2014/02/24 职场文书
工商局调档介绍信
2015/10/22 职场文书
教师读书活动心得体会
2016/01/14 职场文书