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

作者:goldensun 时间:2023-01-26 22:29:28 

从事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
0
投稿

猜你喜欢

  • asp xmlhttp下载一句话

    2013-06-30 06:47:48
  • 怎样开启phpStudy服务器

    2023-05-25 00:38:06
  • 网页设计配色基础:RGB与HSB

    2008-05-06 12:23:00
  • Python3.6实现连接mysql或mariadb的方法分析

    2024-01-26 19:46:36
  • Python读取二进制文件代码方法解析

    2023-06-14 14:32:35
  • Python+Pyecharts实现散点图的绘制

    2023-09-02 05:01:29
  • CentOS 5.5下安装MySQL 5.5全过程分享

    2024-01-16 02:06:57
  • Python人工智能深度学习模型训练经验总结

    2022-01-05 18:10:50
  • 浅析python 定时拆分备份 nginx 日志的方法

    2023-08-04 06:03:37
  • mysql 5.7.14 安装配置方法图文教程

    2024-01-12 14:01:18
  • js+html5通过canvas指定开始和结束点绘制线条的方法

    2024-05-02 17:20:44
  • 基于Python开发chrome插件的方法分析

    2023-04-22 14:41:33
  • 关于计算到期时间的问题

    2009-05-26 15:51:00
  • Python使用StringIO和BytesIO读写内存数据

    2022-06-15 02:45:45
  • 详解python的变量缓存机制

    2023-05-11 07:47:45
  • python人工智能使用RepVgg实现图像分类示例详解

    2021-04-15 21:36:42
  • asp让网站自动识别手机访问跳转至手机网站

    2014-12-06 09:36:02
  • 浅谈SQL Server 对于内存的管理[图文]

    2024-01-14 07:41:44
  • python语音识别的转换方法

    2023-12-06 20:56:57
  • Python利用shutil实现拷贝文件功能

    2022-05-10 05:20:04
  • asp之家 网络编程 m.aspxhome.com