性能测试的艺术

发表于:2018-1-10 13:18

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:磁针石    来源:51Testing软件测试网采编

分享:
 测试结果参见:



  目录结构
  每个测试项目包含以下内容:
  config.cfg的配置文件。用于设定测试选项。
  test_scripts/虚拟用户脚本的目录。在这里添加您的测试脚本。
  results/:结果存储目录。对于每个测试都声称一个时间戳目录,里面包含结果的报告。
  multimech-newproject,默认生成一个随机数的脚本。脚本v_user.py如下:
  import randomimport timeclass Transaction(object):
      def __init__(self):
          pass
      def run(self):
          r = random.uniform(1, 2)
          time.sleep(r)
          self.custom_timers['Example_Timer'] = rif __name__ == '__main__':
      trans = Transaction()
      trans.run()
      print trans.custom_timers
  配置参数的含义如下:
  run_time: duration of test (seconds) 测试的执行时间
  rampup: duration of user rampup (seconds) 多少秒内发完请求
  results_ts_interval: time series interval for results analysis (seconds) 结果分析时间
  progress_bar: turn on/off console progress bar during test run 是否显示进度条
  console_logging: turn on/off logging to stdout 是否输出到stdout
  xml_report: turn on/off xml/jtl report 是否生成xml报告。
  results_database: database connection string (optional) 保存结果的数据库连接字符串(可选)
  post_run_script: hook to call a script at test completion (optional) 调用的善后脚本(可选)
  脚本书写
  用Python书写,测试脚本模拟虚拟用户对网站/服务/ API的请求,脚本定义了用户事务。
  每个脚本必须实现一个Transaction()类。这个类必须实现一个run()方法。基本的测试脚本结构如下:
  class Transaction(object):
      def run(self):
          # do something here
          return
  运行期间,Transaction()实例化一次,run()方法则反复调用:
  class Transaction(object):
      def __init__(self):
          # do per-user user setup here
          # this gets called once on user creation
          return
      def run(self):
          # do user actions here
          # this gets called repeatedly
          return
  从结构上看,如果每次run如果需要setup和teardown,时间也会计算在run里面,会显得事务处理的时间更长。这个就需要使用定时器来精确计时。
  另外脚本建议先调试之后在运行,因为Multi-Mechanize有可能报错不够精准。可以这样运行:# python v_suds.py。v_suds.py是你实际使用的脚本名。另外suds这个库好像实现时性能一般,并发200时,客户端cpu占用率经常会100%,为此web service如果要上大量用户的话,建议用其他库替代,比如soapPy。进一步提升效率可以试用python的ctypes模块,或者cython(性能接近c语言)。不过Multi-Mechanize的多进程是基于python的,实在对性能有相当高的要求,就只能全部用c书写了。
  下例使用mechanize进行web测试。
  class Transaction(object):
      def __init__(self):
          pass
      def run(self):
          br = mechanize.Browser()
          br.set_handle_robots(False)
          resp = br.open('http://192.168.4.13/env.htm')
          assert (resp.code == 200), 'Bad Response: HTTP %s' % resp.codes        assert ('service name' in resp.get_data())
  下面用httplib库重写脚本,并增加定时器。通过定时器,可以分析各个步骤的耗时。
  XHTML
  import httplibimport timeclass Transaction(object):
      def run(self):
          conn = httplib.HTTPConnection('192.168.4.13')
          start = time.time()
          conn.request('GET', '/env.htm')
          request_time = time.time()
          resp = conn.getresponse()
          response_time = time.time()
          conn.close()
          transfer_time = time.time()
          self.custom_timers['request sent'] = request_time - start        self.custom_timers['response received'] = response_time - start        self.custom_timers['content transferred'] = transfer_time - start        assert (resp.status == 200), 'Bad Response: HTTP %s' % resp.statusif __name__ == '__main__':
      trans = Transaction()
      trans.run()
      for timer in ('request sent', 'response received', 'content transferred'):
          print '%s: %.5f secs' % (timer, trans.custom_timers[timer])
  boom:类似ab(ApacheBench)的性能测试工具
  我们先对ApacheBench做个简介,再介绍boom。
  ApacheBench
  ApacheBench简介
  ApacheBench 是一个用来衡量http服务器性能的单线程命令行工具。原本针对Apache http服务器,但是也适用于其他http服务器。
  ab工具与标准 Apache源码一起发布,免费,开源,基于Apache License。
  ApacheBench安装
  ubuntu 14.04 执行“apt-get install apache2-utils“即可。
  ApacheBench快速入门
  发送1000个http get请求到http://192.168.10.232:8000/blog,并发为10:
  XHTML
  # ab -n1000 -c10 http://192.168.10.232:8000/blogThis is ApacheBench, Version 2.3 Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/Licensed to The Apache Software Foundation, http://www.apache.org/Benchmarking 192.168.10.232 (be patient)Completed 100 requests
  Completed 200 requests
  Completed 300 requests
  Completed 400 requests
  Completed 500 requests
  Completed 600 requests
  Completed 700 requests
  Completed 800 requests
  Completed 900 requests
  Completed 1000 requests
  Finished 1000 requests
  Server Software:        tracd/1.0.1Server Hostname:        192.168.10.232Server Port:            8000Document Path:          /blog
  Document Length:        330918 bytesConcurrency Level:      10Time taken for tests:   1353.994 seconds
  Complete requests:      1000Failed requests:        0Total transferred:      331323000 bytesHTML transferred:       330918000 bytesRequests per second:    0.74 [#/sec] (mean)Time per request:       13539.943 [ms] (mean)Time per request:       1353.994 [ms] (mean, across all concurrent requests)Transfer rate:          238.97 [Kbytes/sec] received
  Connection Times (ms)
                min  mean[+/-sd] median   maxConnect:        1    1   0.8      1      17Processing:  8703 13500 640.5  13586   15076Waiting:     8646 13387 641.6  13480   14957Total:       8704 13501 640.5  13587   15079Percentage of the requests served within a certain time (ms)
    50%  13587
    66%  13742
    75%  13848
    80%  13912
    90%  14133
    95%  14315
    98%  14516
    99%  14618
   100%  15079 (longest request)
  注意Time per request: 13539.943 [ms] (mean)是平均每批请求的完成时间,这里时10个请求完成的时间。Time per request: 1353.994 [ms] (mean, across all concurrent requests)是平均每个请求的完成时间。
  ApacheBench将只使用一个操作系统线程。很多情况下ApacheBench本身是瓶颈。当在硬件具有多个处理器核心使用ApacheBench,建议一个cpu核执行一个ab线程,但是现在cpu核数很多的情况下,比如48核,手工执行48个命令也是个体力活。
  整体来说ab因为不能利用到多核、不能进行参数化、不支持http和https以外的协议等原因,只适合单个组件的粗略测试,比如Apache http。不合适业务级别的测试,如一旦后台有数据库等,ab的测试是几乎没有意义的。
  ApacheBench参考
  命令行帮助
  XHTML
  $ ab -h
  Usage: ab [options] [http[s]://]hostname[:port]/path
  Options are:
      -n requests     Number of requests to perform    -c concurrency  Number of multiple requests to make at a time    -t timelimit    Seconds to max. to spend on benchmarking
                      This implies -n 50000
      -s timeout      Seconds to max. wait for each response
                      Default is 30 seconds    -b windowsize   Size of TCP send/receive buffer, in bytes
      -B address      Address to bind to when making outgoing connections    -p postfile     File containing data to POST. Remember also to set -T    -u putfile      File containing data to PUT. Remember also to set -T    -T content-type Content-type header to use for POST/PUT data, eg.
                      'application/x-www-form-urlencoded'
                      Default is 'text/plain'
      -v verbosity    How much troubleshooting info to print
      -w              Print out results in HTML tables    -i              Use HEAD instead of GET    -x attributes   String to insert as table attributes    -y attributes   String to insert as tr attributes    -z attributes   String to insert as td or th attributes    -C attribute    Add cookie, eg. 'Apache=1234'. (repeatable)
      -H attribute    Add Arbitrary header line, eg. 'Accept-Encoding: gzip'
                      Inserted after all normal header lines. (repeatable)
      -A attribute    Add Basic WWW Authentication, the attributes
                      are a colon separated username and password.
      -P attribute    Add Basic Proxy Authentication, the attributes
                      are a colon separated username and password.
      -X proxy:port   Proxyserver and port number to use    -V              Print version number and exit
      -k              Use HTTP KeepAlive feature    -d              Do not show percentiles served table.
      -S              Do not show confidence estimators and warnings.
      -q              Do not show progress when doing more than 150 requests    -l              Accept variable document length (use this for dynamic pages)
      -g filename     Output collected data to gnuplot format file.
      -e filename     Output CSV file with percentages served    -r              Don't exit on socket receive errors.
      -h              Display usage information (this message)
      -Z ciphersuite  Specify SSL/TLS cipher suite (See openssl ciphers)
      -f protocol     Specify SSL/TLS protocol                    (SSL3, TLS1, TLS1.1, TLS1.2 or ALL)
  语法:
  XHTML
  ab [ -A auth-username:password ] [ -b windowsize ] [ -c concurrency ] [ -C cookie-name=value ] [ -d ] [ -e csv-file ] [ -f protocol ] [ -g gnuplot-file ] [ -h ] [ -H custom-header ] [ -i ] [ -k ] [ -n requests ] [ -p POST-file ] [ -P proxy-auth-username:password ] [ -q ] [ -r ] [ -s ] [ -S ] [ -t timelimit ] [ -T content-type ] [ -u PUT-file ] [ -v verbosity] [ -V ] [ -w ] [ -x -attributes ] [ -X proxy[:port] ] [ -y-attributes ] [ -z -attributes ] [ -Z ciphersuite ] [http[s]://]hostname[:port]/path
  1
  ab [ -A auth-username:password ] [ -b windowsize ] [ -c concurrency ] [ -C cookie-name=value ] [ -d ] [ -e csv-file ] [ -f protocol ] [ -g gnuplot-file ] [ -h ] [ -H custom-header ] [ -i ] [ -k ] [ -n requests ] [ -p POST-file ] [ -P proxy-auth-username:password ] [ -q ] [ -r ] [ -s ] [ -S ] [ -t timelimit ] [ -T content-type ] [ -u PUT-file ] [ -v verbosity] [ -V ] [ -w ] [ -x -attributes ] [ -X proxy[:port] ] [ -y-attributes ] [ -z -attributes ] [ -Z ciphersuite ] [http[s]://]hostname[:port]/path
  命令行选项
  XHTML
  -A auth-username:password
      向服务器提供基本认证信息。用户名和密码之间":"分割,以base64编码形式发送。无论服务器是否需要(即是否发送了401)都发送。 
  -b windowsize
      TCP发送/接收缓冲区大小,以字节为单位。
  -c concurrency
      并发数,默认为1。
  -C cookie-name=value
      添加Cookie。典型形式是name=value对。name参数可以重复。 
  -d
  不显示"percentage served within XX [ms] table"消息(兼容以前的版本)。 
  -e csv-file
      输出百分率和对应的时间,格式为逗号份额的csv。由于这种格式已经"二进制化",所以比"gnuplot"格式更有用。
  -f protocol
      SSL/TLS protocol (SSL2, SSL3, TLS1, 或ALL).
  -g gnuplot-file
      把所有测试结果写入"gnuplot"或者TSV(以Tab分隔)文件。该文件可以方便地导入到Gnuplot, IDL, Mathematica甚至Excel中,第一行为标题。
  -h
      显示使用方法。
  -H custom-header
      附加额外头信息。典型形式有效的头信息行,包含冒号分隔的字段和值(如:"Accept-Encoding: zip/zop;8bit")。
  -i
      执行HEAD请求,而不是GET 。
  -k
      启用KeepAlive功能,即在HTTP会话中执行多个请求。默认关闭。
  -n requests
      会话执行的请求数。默认为1。 
  -p POST-file
      附加包含POST数据的文件。注意和-T一起使用。
  -P proxy-auth-username:password
      代理认证。用户名和密码之间":"分割,以base64编码形式发送。无论服务器是否需要(即是否发送了407)都发送。
  -q
      quiet,静默模式。不在stderr输出进度条。
  -r
      套接字接收错误时不退出。
  -s timeout 
      超时,默认为30秒。
  -S
      不显示中值和标准偏差值,而且在均值和中值为标准偏差值的1到2倍时,也不显示警告或出错信息。默认显示最小值/均值/最大值。(兼容以前的版本)-t timelimit
      测试进行的最大秒数。内部隐含值是"-n 50000"。默认没有时间限制。
  -T content-type
      POST/PUT的"Content-type"头信息。比如“application/x-www-form-urlencoded”,默认“text/plain”。
  -v verbosity
      详细模式,4以上会显示头信息,3以上显示响应代码(404,200等),2以上显示告警和info。
  -V
      显示版本号并退出。
  -w
      以HTML表格形式输出。默认是白色背景的两列。
  -x -attributes
  设置属性。此属性填入
  -X proxy[:port]
  使用代理服务器。
  -y -attributes
  设置属性。
  -z -attributes
  设置属性。
  -Z ciphersuite
  设置SSL/TLS加密
  结果分析字段
  XHTML
  Server Software
      返回的第一次成功的服务器响应的HTTP头。
  Server Hostname
      命令行中给出的域名或IP地址
  Server Port
      命令行中给出端口。如果没有80(HTTP)和443(HTTPS)。
  SSL/TLS Protocol
      使用SSL打印。
  Document Path
      命令行请求的路径。
  Document Length
      第一次成功地返回文档的字节大小。后面接受的文档长度变化时,会认为是错误。
  Concurrency Level
      并发数
  Time taken for tests
      测试耗时
  Complete requests
      收到成功响应数
  Failed requests
      失败请求数。如果有会打印错误原因
  Write errors
     写错误数 (broken pipe)Non-2xx responses
      非2**响应数量。如果有打印。
  Keep-Alive requests
      Keep-Alive请求的连接数
  Total body sent:
      传输的body的数据量,比如POST的数据。
  Total transferred:
      总传输数据量
  HTML transferred:       
      累计html传输数据量
  Time per request:      
      每批平均请求时间
  Time per request: 
      每次平均请求时间。计算公式:Time per request/Concurrency Level。
  Transfer rate
      数据传输速率。计算公式:otalread / 1024 / timetaken。
  boom
  boom简介
  boom是python替代ab的模块,并增加了部分功能。
  boom安装
  ubuntu 14.04 执行“pip install boom“即可,注意可能需要先执行”apt-get install libevent python-dev”。它使用Gevent创建虚拟用户,使用Requests发送请求。
  boom快速入门
  XHTML
  # boom -n1000 -c10 http://192.168.10.232:8000/blogServer Software: tracd/1.0.1 Python/2.7.3Running GET http://192.168.10.232:8000/blog
  Running 1000 times per 10 workers.[================================================================>.] 99% Done-------- Results --------Successful calls                1000Total time                      1355.1412 s
  Average                         13.5156 s
  Fastest                         8.2434 s
  Slowest                         15.3094 s
  Amplitude                       7.0660 s
  RPS                             0BSI                             Hahahaha-------- Status codes --------Code 200                        1000 times.-------- Legend --------RPS: Request Per Second
  BSI: Boom Speed Index
  Average:每批请求的平均处理时间。 Fastest:每批请求的最快处理时间。 Slowest:每批请求的最慢处理时间。 Amplitude:振幅,即最慢与最忙批次处理时间差。
  boom参考
  XHTML
  $ boom -h
  usage: boom [-h] [--version] [-m {GET,POST,DELETE,PUT,HEAD,OPTIONS}]
              [--content-type CONTENT_TYPE] [-D DATA] [-c CONCURRENCY] [-a AUTH]
              [--header HEADER] [--hook HOOK] [--json-output]
              [-n REQUESTS | -d DURATION]
              [url]Simple HTTP Load runner.positional arguments:
    url                   URL to hit
  optional arguments:
    -h, --help            show this help message and exit
    --version             Displays version and exits.
    -m {GET,POST,DELETE,PUT,HEAD,OPTIONS}, --method {GET,POST,DELETE,PUT,HEAD,OPTIONS}
                          HTTP Method  --content-type CONTENT_TYPE
                          Content-Type  -D DATA, --data DATA  Data. Prefixed by "py:" to point a python callable.
    -c CONCURRENCY, --concurrency CONCURRENCY
                          Concurrency  -a AUTH, --auth AUTH  Basic authentication user:password  --header HEADER       Custom header. name:value  --hook HOOK           Python callable that'll be used on every requests call
    --json-output         Prints the results in JSON instead of the default
                          format  -n REQUESTS, --requests REQUESTS
                          Number of requests  -d DURATION, --duration DURATION
                          Duration in seconds
  结论
  ab和boom在功能上远不及multi-mechanize和Grinder等主力python性能测试工具,甚至还比不上庞大且扩能能力差的loadrunner。只建议在对单个中间件的基准测试时使用。
  locustio
  什么是locustio?
  Locust是易于使用、分布式的用户负载测试工具。用于网站(或其他系统)的负载测试,计算出系统可以处理并发用户数。
  测试时大量蝗虫会攻击你的网站。每只蝗虫(或叫测试用户)可以自定义、测试过程由web界面实时监控。这能帮助测试并确定瓶颈。
  Locust 完全基于的事件,单机可以支持数千用户。它不使用回调,而是基于轻量进程gevent, 能简单地实线各种场景。
  特点
  ●Python书写场景
  无需笨重的UI或XML。仅仅是代码,协程而不是回调。
  ●分布式,可扩展和,支持成千上万的用户
  ●基于Web的用户界面
  Locust有整洁HTML + JS用户界面,实时展示测试细节,跨平台和易于扩展。
  ●可以测试任何系统
  ●可控制
  事件完全由gevent处理。
  背景
  我们研究了现有的解决方案,都不符合要求。比如Apache JMeter和Tsung。JMeter基于UI操作,容易上手,但基本上不具备编程能力。其次JMeter基于线程,要模拟数千用户几乎不可能。 Tsung基于Erlang,能模拟上千用户并易于扩展,但它它基于XML的DSL,描述场景能力弱,且需要大量的数据处理才知道测试结果。
  无论如何,我们试图解决创建蝗虫,当这些问题。希望以上都不是painpoints应该存在。
  我想你可以说我们真的只是想在这里从头开始自己的痒。我们希望其他人会发现,因为我们做的是有益的。
  ●作者
  Jonatan Heyman (@jonatanheyman on Twitter)
  Carl Bystr?m (@cgbystrom on Twitter)
  Joakim Hamrén (@Jahaaja on Twitter)
  Hugo Heyman (@hugoheyman on Twitter)
  License: MIT
  安装
  安装:”pip install locustio”或者”easy_install locustio”
  检验:
  执行”locust –help”能看到如下信息表示安装成功:
  XHTML
  # locust --help
  Usage: locust [options] [LocustClass [LocustClass2 ... ]]
  Options:
    -h, --help            show this help message and exit
  ...
  主要需要 Python 2.6+,不支持python3。分布式测试还需要安装pyzmq。尽管locustio可以在Windows运行,但是考虑效率不推荐
  快速入门
  下面我们访问http://automationtesting.sinaapp.com/的首页和about页面。
  编写脚本
  XHTML
  #!/usr/bin/env python# coding=utf-8"""
  Locust quickstart!
  Copyright 2015.05.08 Rongzhong.Xu xurongzhong#126.com
  http://automationtesting.sinaapp.com
  """from locust import HttpLocust, TaskSet, taskclass UserBehavior(TaskSet):
      """
      Locust test class
      """
      def on_start(self):
          """ called when a Locust start before any task is scheduled """
          self.login()
      def login(self):
          "pass"
          pass
      @task(2)
      def index(self):
          "http://automationtesting.sinaapp.com/"
          self.client.get("/")
      @task(1)
      def about(self):
          "http://automationtesting.sinaapp.com/about"
          self.client.get("/about")class WebsiteUser(HttpLocust):
      """
      The HttpLocust class inherits from the Locust class, and it adds
      a client attribute which is an instance of HttpSession,
      that can be used to make HTTP requests.
      """
      task_set = UserBehavior
      min_wait = 5000
      max_wait = 9000
  HttpLocust继承自Locust,添加了client属性。client属性是HttpSession实例,可以用于生成HTTP请求。
  on_start为client初始化时执行的步骤。
  task表示下面方法是测试内容,里面的数字执行比例,这里about页面占三分之一,主页占三分之二。
  task_set指定client执行的类。min_wait和max_wait为两次执行之间的最小和最长等待时间。
  启动
  启动locust后台
  XHTML
  # locust --host=http://automationtesting.sinaapp.com
  [2015-05-08 16:33:49,166] andrew-Hi-Fi-A88S2/INFO/locust.main: Starting web monitor at *:8089
  [2015-05-08 16:33:49,167] andrew-Hi-Fi-A88S2/INFO/locust.main: Starting Locust 0.7.2
  在浏览器启动locust
  打开http://127.0.0.1:8089/,配置模拟的用户数”Number of users to simulate”和每秒发起的用户数”Hatch rate”,提交执行测试。
  这时在浏览器就可以看到实时的测试结果。点击浏览器上方的”stop”即可停止测试。
  查看报告:
  命令行按Ctrl + c , 可以显示一些摘要
  XHTML
   # locust --host=http://automationtesting.sinaapp.com
  [2015-05-08 16:33:49,166] andrew-Hi-Fi-A88S2/INFO/locust.main: Starting web monitor at *:8089
  [2015-05-08 16:33:49,167] andrew-Hi-Fi-A88S2/INFO/locust.main: Starting Locust 0.7.2
  [2015-05-08 16:42:18,656] andrew-Hi-Fi-A88S2/INFO/locust.runners: Hatching and swarming 8 clients at the rate 2 clients/s...
  [2015-05-08 16:42:22,663] andrew-Hi-Fi-A88S2/INFO/locust.runners: All locusts hatched: WebsiteUser: 8
  [2015-05-08 16:42:22,663] andrew-Hi-Fi-A88S2/INFO/locust.runners: Resetting stats
  ^C[2015-05-08 16:48:19,884] andrew-Hi-Fi-A88S2/ERROR/stderr: KeyboardInterrupt
  [2015-05-08 16:48:19,884] andrew-Hi-Fi-A88S2/INFO/locust.main: Shutting down (exit code 0), bye.
   Name                                                          # reqs      # fails     Avg     Min     Max  |  Median   req/s
  --------------------------------------------------------------------------------------------------------------------------------------------
   GET /                                                             36     0(0.00%)     260     206     411  |     250    0.90
   GET /about                                                        17     0(0.00%)     199     146     519  |     170    0.10
  --------------------------------------------------------------------------------------------------------------------------------------------
   Total                                                             53     0(0.00%)                                       1.00
  Percentage of the requests completed within given times
   Name                                                           # reqs    50%    66%    75%    80%    90%    95%    98%    99%   100%
  --------------------------------------------------------------------------------------------------------------------------------------------
   GET /                                                              36    250    260    260    270    370    400    410    410    411
   GET /about                                                         17   &nb

上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。
33/3<123
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号