利用nGrinder进行性能测试操作指南

nGrinder简介

nGrinder是基于Grinder开源项目,但由NHN公司的nGrinder开发团队进行了重新设计和完善(所以叫做nGrinder)。nGrinder是一款非常易用,有友好简洁的用户界面和controller-agent分布式结构的强大的压力测试工具。

它是由一个controller和连接它的多个agent组成,用户可以通过web界面管理和控制测试,以及查看测试报告,controller会把测试分发到一个或多个agent去执行。用户可以设置使用多个进程和线程来并发的执行该脚本,而且在同一线程中,来重复不断的执行测试脚本,来模拟很多并发用户。

nGrinder的测试是基于一个python的测试脚本,用户按照一定规则编写测试脚本以后,controller会将脚本以及需要的其他文件分发到agent,用Jython执行。并在执行过程中收集运行情况、响应时间、测试目标服务器的运行情况等。并保存这些数据生成运行报告,以供以后查看。

nGrinder的一大特点就是非常容易使用,安装也非常容易,可以做到开箱即用,测试用户也可以很容易就开始测试任务。当然,如果想执行一些比较复杂场景的性能测试,就需要测试人员对python有一定认识。

ngrinder-image (1)

nGrinder的安装

先决条件

nGrinder是一个web应用(Controller)和Java应用(Agent, Monitor)的组合。安装 nGrinder的Controller和Agent,需要安装JDK 1.6或更高的版本。.

nGrinder需要用到很多端口。如果有些端口被防火墙阻挡,请联系服务器管理开放下面这些端口。

  • Agent : Any ==> Controller : 16001
  • Agent : Any ==> Controller : 12000 ~ 12000+(允许并发测试的数量)
  • Controller : Any ==> Monitor : 13243
  • Controller ==> Public user : 这取决于你的Tomcat的配置,默认为8080。

下载

先从下面位置下载nGrinder:

http://sourceforge.net/projects/ngrinder/files

安装Controller

nGrinder的安装文件是作为一个可自执行的网络存档文件(WAR包)分发的。像Jenkins一样,你可以把这个存档文件放到你熟悉的Web应用服务器(像Tomcat)中,或者在命令行中直接运行。

千万注意,别将文件放到包含空格的文件夹路径中,比如:”C:\Program Files\Tomcat\webapps\”。

作为一个自执行程序运行

  1. 请确定正确安装了JAVA的SDK,很多问题都是没有正确配置环境变量导致的。
  2. 用下面的命令运行nGrinder controller:
java -jar ngrinder-controller-X.X.war
  1. 然后你会看到如下的错误信息。
nGrinder requires very big PermGen memory because it includes very many libraries such as  SVNKit, maven, Jetty webserver, groovy, and python. Re-run the ngrinder with the PermGen settings.

nGrinder需要更多的perm-gen 内存空间,请重新用下面的命令运行nGrinder。

java -XX:MaxPermSize=200m -jar  ngrinder-controller-3.3.war
  1. 请注意,nGrinder用8080作为web端访问的端口,如果你想使用其他的端口,请增加参数配置–port port_number。
java -XX:MaxPermSize=200m -jar  ngrinder-controller-3.3.war --port 80
  1. 当执行这个war包文件,war包中的文件会解压到~/.ngrinder/webapp文件夹中并创建默认数据文件到.ngrinder文件夹中。
  2. 如果你能在屏幕中看见下面的日志信息,说明ngridner controller已经正常启动运行。
INFO 14. 1. 20 오후 4:39:liquibase: ChangeSet ngrinder_datachange_logfile/db.changelog_schema_22.xml::22::ngrinder.3.3 r
an successfully in 4ms
INFO 14. 1. 20 오후 4:39:liquibase: ChangeSet ngrinder_datachange_logfile/db.changelog_schema_23.xml::23::ngrinder.3.3 r
an successfully in 7ms
INFO 14. 1. 20 오후 4:39:liquibase: ChangeSet ngrinder_datachange_logfile/db.changelog_schema_24.xml::24::ngrinder.3.3 r
an successfully in 2ms
INFO 14. 1. 20 오후 4:39:liquibase: ChangeSet ngrinder_datachange_logfile/db.changelog_schema_25.xml::25::ngrinder.3.3 r
an successfully in 7ms
INFO 14. 1. 20 오후 4:39:liquibase: ChangeSet ngrinder_datachange_logfile/db.changelog_schema_26.xml::26::ngrinder.3.3 r
an successfully in 8ms
2014-01-20 16:39:30.633:INFO:/:Initializing Spring FrameworkServlet 'appServlet'
2014-01-20 16:39:31.141:INFO::Started SocketConnector@@0.0.0.0:8080

 

  1. 现在可以打开浏览器访问http://localhost:8080/使用nGrinder了。

在Tomcat中运行

  1. 将war包文件放到tomcat的webapps文件夹中,${TOMCAT_HOME}/webapps 。如果你不想通过路径ngrinder-controller访问nGrinder,可以修改war包文件的名称为war.
  2. 然后打开sh或者catalina.bat将下面这行命令添加到文件头部。
JAVA_OPTS="-Xms600m -Xmx1024m -XX:MaxPermSize=200m"    # for catalina.sh

set JAVA_OPTS=-Xms600m -Xmx1024m -XX:MaxPermSize=200m   # for catalina.bat
  1. 然后运行${TOMCAT_HOME}/startup.sh或者bat
  2. 打开浏览器访问http://localhost:8080/ngrinder-controller-X.X或者http://localhost:8080如果你修改了war包文件的名称为war

安装Agents

nGrinder 3.3的 agents可以通过controller页面中的链接直接下载使用。下载的包中agents的相关配置已经默认配置好了,所以可以直接解压包,并运行“run_agent.sh”或者“run_agent.bat”启动agents,让其和controller通信。

  1. 通过admin帐号登录nGrinder,admin的默认密码是admin。ngrinder-image (2)
  2. 点击顶部右侧菜单中的Download Agent进行下载。ngrinder-image (3)
  3. 因为使用的是admin帐号登录,下载的agents包中的配置可以分享给所有的用户使用。如果你登录的是一个普通帐号,下载链接将变成“Download Private Agent” 下载的agents包中的配置只能当前用户使用。
  4. 解压包并且运行其中的sh或者run_agent.bat即可。
  5. 如果你想停止运行agent,执行下面命令。
    stop_agent.sh # for linux / mac
    stop_agent.bat # for windows
  6. 可以点击右上角菜单中的agents management链接进入agents管理页面。ngrinder-image (4)
  7. 如果agent运行在Linux下,你可能需要配置ulimit让其运行更多的线程。请检查下面的配置。
 >ulimit -a

core file size          (blocks, -c) 0

data seg size           (kbytes, -d) unlimited

scheduling priority             (-e) 0

file size               (blocks, -f) unlimited

pending signals                 (-i) 30676

max locked memory       (kbytes, -l) 64

max memory size         (kbytes, -m) unlimited

open files                      (-n) 16000

pipe size            (512 bytes, -p) 8

POSIX message queues     (bytes, -q) 819200

real-time priority              (-r) 0

stack size              (kbytes, -s) 10240

cpu time               (seconds, -t) unlimited

max user processes              (-u) 32768

virtual memory          (kbytes, -v) unlimited

file locks                      (-x) unlimited

安装Monitor

nGrinder的Monitor是agent的一个子集,是安装在目标服务器中的用于收集系统相关数据(比如CPU, MEM and Network) 的程序。

你可以通过右上角菜单下载monitors。

  1. 下载monitor。
    ngrinder-image (5)
  2. 解压monitor的包并运行下面的命令:
    run_monitor_bg.sh  # for linux / mac
    run_monitor.bat # for windows
  3. 停止monitor,运行下面的命令:
stop_monitor.sh # for linux / mac

stop_monitor.bat –o # for windows

测试步骤

nGrinder运行一个压力测试只需3步:

1)Python脚本编写测试场景;

2)配置虚拟用户数,周期,步长控制,资源监控;

3)运行结束报告自动生成,TPS/MeanTime/Errors, 监控CPU/Memory…… 。

用过压力工具的同学们都知道,常常是简单的工具不合用,合用的工具不简单,怎么也得连培训带自己琢磨各种Guide和Manual,好几天时间才能上手。并发量是需要大量的money来换的,付费证书过期就肯定不能用的。nGrinder可以颠覆你对压力工具的各种印象!之前没有经验的同学也3分钟能上手,半天时间会部署,如果会Jython的同学,就可以进行你能想到的各种测试场景的压力测试了。

简单的测试案例

登录nGrinder后,你可以通过输入一个测试的url,然后执行测试,nGrinder会自动生成测试脚本。

image010

输入一个有效的测试链接,选择脚本语言(比如Jython)后,点击开始测试,进入配置页面。

image012

在配置界面,可以配置启用多少agents,每个agent启动多少个虚拟用户数,虚拟用户启动的方式。也可以配置测试执行的时间,将使用哪个版本的测试脚本,配置目标服务器的域名以及DNS解析等。

ngrinder-image (8)

自动生成的脚本是检查输入的链接是不是返回200,可以根据自己的需要修改脚本。

ngrinder-image (9)

回到配置页面,右上角有保存和保存并执行两个按钮,点击保存并执行,启动测试。

ngrinder-image (10)

可以选择马上运行,或者设置预约时间定时执行。

image020

image022

可以将鼠标移动到右上角查看运行状态。

image024

当测试启动后,会在页面中显示当前的TPS,虚拟用户数,测试成功和失败的数量等信息。测试完成后,显示如下的页面。

image025

可以点击页面中的详细测试结果按钮,查看详细的测试数据。

image027

页面显示了TPS图,平均响应时间图,错误图,首次接收数据的平均时间等信息。

在模板服务器启动了monitor时,可以在此页面查看目标服务器的服务器相关资源消耗情况。

多页面的测试案例

上面演示了测试一个单链接的情况,但实际在模拟场景时,我们会考虑多个页面或者多个资源加载的情况。那就需要修改测试脚本,模拟多页面加载的情况,参考脚本如下:

# -*- coding:utf-8 -*-

# A simple example using the HTTP plugin that shows the retrieval of a
# single page via HTTP. 
#
# This script is automatically generated by ngrinder.
#
# @author admin
from net.grinder.script.Grinder import grinder
from net.grinder.script import Test
from net.grinder.plugin.http import HTTPRequest
from net.grinder.plugin.http import HTTPPluginControl
from HTTPClient import NVPair
import PTS #自定义的库,后续大家可扩充。

control = HTTPPluginControl.getConnectionDefaults()
# if you don't want that HTTPRequest follows the redirection, please modify the following option 0.
# control.followRedirects = 1
# if you want to increase the timeout, please modify the following option.
control.timeout = 600000 #超时时间10分钟

#定义第一页
def page01():
    statusCode = [0L,0L,0L,0L]

    headers = [ NVPair('Accept', '*/*'), NVPair('Accept-Encoding', 'gzip, deflate, sdch'), NVPair('Accept-Language', 'zh-CN,zh;q=0.8'), NVPair('User-Agent', 'PTS-HTTP-CLIENT'), ]
    result = HTTPRequest().GET('http://u.pre.liveapp.com.cn/60032', None, headers)
    PTS.addHttpCode(result.getStatusCode(),statusCode)
    grinder.sleep(1000) #等待1秒钟
    return statusCode

#定义第二页
def page02():
    statusCode = [0L,0L,0L,0L]

    headers = [ NVPair('Accept', '*/*'), NVPair('Accept-Encoding', 'gzip, deflate, sdch'), NVPair('Accept-Language', 'zh-CN,zh;q=0.8'), NVPair('User-Agent', 'PTS-HTTP-CLIENT'), ]
    result = HTTPRequest().GET('http://u.pre.liveapp.com.cn/60032', None, headers)
    PTS.addHttpCode(result.getStatusCode(),statusCode)
    grinder.sleep(500) 
    return statusCode

# Make any method call on request1 increase TPS
Test(1,'load case 60032 01').record(page01)
Test(2,'load case 60032 02').record(page02)

class TestRunner:
    # initlialize a thread 
    def __init__(self):
        grinder.statistics.delayReports=True
        pass

    # test method       
    def __call__(self):
        sumStatusCode = [0L,0L,0L,0L]
        PTS.sumHttpCode(page01(),sumStatusCode)
        PTS.sumHttpCode(page02(),sumStatusCode)
        
        # if you want to print out log.. Don't use print keyword. Instead, use following.
        #grinder.logger.info(str(sumStatusCode))
        
        # statusCode[0]代表http code < 300 个数,    statusCode[1] 代表 300<=http code<400 个数
        # statusCode[2]代表400<=http code<500个数,  statusCode[3] 代表 http code >=500个数
        # 如果http code 300 到 400 之间是正常的
        # 那么判断事务失败,请将statusCode[1:4] 改为   statusCode[2:4] 即可
        if sum(sumStatusCode[1:4]) > 0 :
            grinder.statistics.forLastTest.success = 0
            grinder.logger.error(u'事务请求中http 返回状态大于300,请检查请求是否正确!')
        else :
            grinder.statistics.forLastTest.success = 1

利用工具录制脚本

在实际的测试过程中,我们需要测试加载很多资源的情况,但是一条一条链接的去写,非常费时间,那我们可以利用录制工具,帮助我们自动生成测试脚本。

nGrinder自带有录制工具,但是并不是很好用(安装略麻烦),前段时间研究过阿里云的性能测试服务PTS,发现阿里的测试平台跟nGrinder很像(看部分脚本,感觉也是基于grinder开发的),同样的使用Jython作为测试脚本开发语言,所以我们可以利用阿里云测试的录制脚本插件来帮助我们进行测试脚本的生成。

安装插件

Chrome插件下载地址:http://pts.aliyun.com/common/Aliyun-PTS-Record-Tool_v.0.2.6.4.crx?file=Aliyun-PTS-Record-Tool_v.0.2.6.4.crx

1、打开Chrome浏览器,URL框内输入chrome://extensions/,进入扩展程序安装页面。

image029

2、将下载的文件拖动至Chrome浏览器窗口,浏览器弹出确认新增扩展程序框,点击添加安装。

image030

3、安装完成后浏览器右上角会出现PTS Logo。

image031

录制脚本

对于复杂的业务,例如登陆、考试、订购、购买、发帖、回帖、退出等业务,由于捕获请求内容或者手工编写脚本工作量稍大,可以使用PTS基于Firefox(支持37及以下版本)和Chrome浏览器插件录制工具。

通过使用此工具,用户在被测系统中进行手工操作业务,录制工具会将用户的操作行为进行录制,录制完成以后,自动生成脚本,根据业务规则可能稍微修改一下脚本,就可以运行脚本了,录制下来的脚本模拟了用户真实的操作行为,极大地方便用户的使用。

工具安装后打开浏览器点击右上角PTS录制工具Logo,弹出录制工具框和浏览器

image032

定义事务名,在浏览器输入URL进行访问操作,录制工具会自动记录访问操作过程中的HTTP请求

image034

录制工具默认只显示HTML类型HTTP的录制请求,如需显示其他类型请求请点击内容过滤选择需要显示的类型请求。

image036

录制完成后点击停止录制按钮,如果需要预览录制生成的脚本,请点击脚本预览按钮。

image038

修改脚本

我们拿到脚本后,需要做一些修改,把不需要的删掉,其实我们只需要def actionX(self)中的脚本,其他的都不需要。

image040

如图,每一个headers段就是一个url链接,根据需要保留需要测试的url。将脚本中的PTS.Framework.addHttpCode(result.getStatusCode(), statusCode)修改成PTS.addHttpCode(result.getStatusCode(), statusCode),删除下面所示部分代码

image042

最终我们需要的脚本变成如下所示:

def action1():
    statusCode = [0L, 0L, 0L, 0L]        

    headers = [ NVPair('Accept', '*/*'), NVPair('Accept-Encoding', 'gzip, deflate, sdch'), NVPair('Accept-Language', 'zh-CN,zh;q=0.8'), NVPair('User-Agent', 'PTS-HTTP-CLIENT'), ]
    result = HTTPRequest().GET('http://u.pre.liveapp.com.cn/60032', None, headers)
    PTS.addHttpCode(result.getStatusCode(), statusCode)

    headers = [ NVPair('Accept', '*/*'), NVPair('Referer', 'http://u.pre.liveapp.com.cn/60032'), NVPair('Accept-Encoding', 'gzip, deflate, sdch'), NVPair('Accept-Language', 'zh-CN,zh;q=0.8'), NVPair('User-Agent', 'PTS-HTTP-CLIENT'), ]
    result = HTTPRequest().GET('http://u.pre.liveapp.com.cn/tpl/all.css?20150729134231', None, headers)
    PTS.addHttpCode(result.getStatusCode(), statusCode)

    headers = [ NVPair('Accept', '*/*'), NVPair('Referer', 'http://u.pre.liveapp.com.cn/60032'), NVPair('Accept-Encoding', 'gzip, deflate, sdch'), NVPair('Accept-Language', 'zh-CN,zh;q=0.8'), NVPair('User-Agent', 'PTS-HTTP-CLIENT'), ]
    result = HTTPRequest().GET('http://u.pre.liveapp.com.cn/web/common/js/bi/bi.js?v=1.0.0', None, headers)
    PTS.addHttpCode(result.getStatusCode(), statusCode)

    headers = [ NVPair('Accept', '*/*'), NVPair('Referer', 'http://u.pre.liveapp.com.cn/60032'), NVPair('Accept-Encoding', 'gzip, deflate, sdch'), NVPair('Accept-Language', 'zh-CN,zh;q=0.8'), NVPair('User-Agent', 'PTS-HTTP-CLIENT'), ]
    result = HTTPRequest().GET('http://u.pre.liveapp.com.cn/web/common/js/bi/bi-post.js?v=1.0.0', None, headers)
    PTS.addHttpCode(result.getStatusCode(), statusCode)

    headers = [ NVPair('Accept', '*/*'), NVPair('Referer', 'http://u.pre.liveapp.com.cn/60032'), NVPair('Accept-Encoding', 'gzip, deflate, sdch'), NVPair('Accept-Language', 'zh-CN,zh;q=0.8'), NVPair('User-Agent', 'PTS-HTTP-CLIENT'), ]
    result = HTTPRequest().GET('http://u.pre.liveapp.com.cn/tpl/all.js?20150729134231', None, headers)
    PTS.addHttpCode(result.getStatusCode(), statusCode)

    return statusCode

这个函数中的内容就是我们需要的,之前举例中的page01,替换掉page01中的内容为新的脚本即可,后续调试代码无误后,就可以开始执行测试了。

“利用nGrinder进行性能测试操作指南”的一个回复

发表评论

电子邮件地址不会被公开。 必填项已用*标注