使用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通过PIL获取图片主要颜色并和颜色库进行对比的方法
Mar 19 Python
python开启多个子进程并行运行的方法
Apr 18 Python
详解Python中expandtabs()方法的使用
May 18 Python
浅析Python的web.py框架中url的设定方法
Jul 11 Python
python opencv判断图像是否为空的实例
Jan 26 Python
Python企业编码生成系统之系统主要函数设计详解
Jul 26 Python
简单了解python中的与或非运算
Sep 18 Python
Python生成器next方法和send方法区别详解
May 30 Python
python 解决pycharm运行py文件只有unittest选项的问题
Sep 01 Python
Python读取图像并显示灰度图的实现
Dec 01 Python
详解用 python-docx 创建浮动图片
Jan 24 Python
Python实现PIL图像处理库绘制国际象棋棋盘
Jul 16 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中把有符号整型转换为无符号整型方法
2015/05/27 PHP
php之可变函数的实例详解
2017/09/13 PHP
Javascript基础教程之定义和调用函数
2015/01/18 Javascript
JavaScript对象属性检查、增加、删除、访问操作实例
2015/07/08 Javascript
基于Angularjs+mybatis实现二级评论系统(仿简书)
2017/02/13 Javascript
JS排序之选择排序详解
2017/04/08 Javascript
浅谈angular2 组件的生命周期钩子
2017/08/12 Javascript
vue 实现全选全不选的示例代码
2018/03/29 Javascript
VUE基于NUXT的SSR 服务端渲染
2018/11/30 Javascript
vue axios封装及API统一管理的方法
2019/04/18 Javascript
ant-design-vue 时间选择器赋值默认时间的操作
2020/10/27 Javascript
python生成随机验证码(中文验证码)示例
2014/04/03 Python
Python 多线程搜索txt文件的内容,并写入搜到的内容(Lock)方法
2019/08/23 Python
Anaconda 查看、创建、管理和使用python环境的方法
2019/12/03 Python
Python PyInstaller库基本使用方法分析
2019/12/12 Python
Python爬虫库requests获取响应内容、响应状态码、响应头
2020/01/25 Python
基于django micro搭建网站实现加水印功能
2020/05/22 Python
使用Keras实现简单线性回归模型操作
2020/06/12 Python
Python 保存加载mat格式文件的示例代码
2020/08/04 Python
python的launcher用法知识点总结
2020/08/07 Python
VICHY薇姿英国官网:全球专业敏感肌护肤领先品牌
2017/07/04 全球购物
世界上第一个创建了罩杯系统的美国内衣品牌:Maidenform
2019/03/23 全球购物
丝芙兰意大利官方网站:Sephora.it
2019/12/13 全球购物
高中毕业自我评价
2014/02/08 职场文书
营销与策划专业求职信
2014/06/20 职场文书
读群众路线的心得体会
2014/09/03 职场文书
2014领导班子正风肃纪思想汇报
2014/09/18 职场文书
“四风”问题自我剖析材料思想汇报
2014/09/23 职场文书
简易离婚协议书范本2014
2014/10/15 职场文书
电工实训报告总结
2014/11/05 职场文书
门市房租房协议书
2014/12/04 职场文书
环卫工人慰问信
2015/02/15 职场文书
罚款通知怎么写
2015/04/22 职场文书
2015秋季田径运动会广播稿
2015/08/19 职场文书
学习党章心得体会2016
2016/01/15 职场文书
忠诚教育学习心得体会
2016/01/23 职场文书