使用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编程入门的一些基本知识
May 13 Python
使用Python对Csv文件操作实例代码
May 12 Python
Python实现合并同一个文件夹下所有PDF文件的方法示例
Apr 28 Python
python处理数据,存进hive表的方法
Jul 04 Python
python cumsum函数的具体使用
Jul 29 Python
postman传递当前时间戳实例详解
Sep 14 Python
tensorflow常用函数API介绍
Apr 19 Python
Python结合Window计划任务监测邮件的示例代码
Aug 05 Python
Python SMTP发送电子邮件的示例
Sep 23 Python
在Windows下安装配置CPU版的PyTorch的方法
Apr 02 Python
Python进阶学习之带你探寻Python类的鼻祖-元类
May 08 Python
Python爬虫之自动爬取某车之家各车销售数据
Jun 02 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
15种PHP Encoder的比较
2007/04/17 PHP
PHP session有效期session.gc_maxlifetime
2011/04/20 PHP
php实现遍历目录并删除指定文件中指定内容
2015/01/21 PHP
PHP编辑器PhpStrom运行缓慢问题
2017/02/21 PHP
PHP中error_reporting函数用法详细介绍
2017/06/11 PHP
php无限极分类实现方法分析
2019/07/04 PHP
基于jquery 的一个progressbar widge
2010/10/29 Javascript
javascript数字数组去重复项的实现代码
2010/12/30 Javascript
JS基础之undefined与null的区别分析
2011/08/08 Javascript
js模拟C#中List的简单实例
2014/03/06 Javascript
Javascript快速排序算法详解
2014/12/03 Javascript
基于jquery实现页面滚动到底自动加载数据的功能
2015/12/19 Javascript
Node.js批量给图片加水印的方法
2016/11/15 Javascript
jQuery实现百度登录框的动态切换效果
2017/04/21 jQuery
AngularJS解决ng-if中的ng-model值无效的问题
2017/06/21 Javascript
vue3.0 CLI - 2.4 - 新组件 Forms.vue 中学习表单
2018/09/14 Javascript
详解基于electron制作一个node压缩图片的桌面应用
2019/01/29 Javascript
Bootstrap table 实现树形表格联动选中联动取消功能
2019/09/30 Javascript
JQuery使用属性addClass、removeClass和toggleClass实现增加和删除类操作示例
2019/11/18 jQuery
在vscode 中设置 vue模板内容的方法
2020/09/02 Javascript
python完成FizzBuzzWhizz问题(拉勾网面试题)示例
2014/05/05 Python
从零学Python之hello world
2014/05/21 Python
python实现贪吃蛇游戏
2020/03/21 Python
使用APScheduler3.0.1 实现定时任务的方法
2019/07/22 Python
如何使用python写截屏小工具
2020/09/29 Python
css3背景_动力节点Java学院整理
2017/07/11 HTML / CSS
行政办公员自我评价分享
2013/12/14 职场文书
后勤服务中心总经理工作职责
2014/03/03 职场文书
高中教师考核方案
2014/05/18 职场文书
感恩祖国演讲稿
2014/09/09 职场文书
教师考核表个人总结
2015/02/12 职场文书
交通事故赔偿起诉书
2015/05/20 职场文书
老干部座谈会主持词
2015/07/03 职场文书
小公司融资,商业计划书的8切记
2019/07/15 职场文书
python3使用diagrams绘制架构图的步骤
2021/04/08 Python
win10电脑老是死机怎么办?win10系统老是死机的解决方法
2022/08/05 数码科技