原文地址: 使用ngrinder进行数据库性能测试 java
nGrinder是一个开源的性能测试系统,项目主页:http://www.nhnopensource.org/ngrinder/。 python
nGrinder是将python脚本部署到多台agent机器,而后根据配置使用多进程多线程执行,达到高并发的测试目的。agent端使用jython来执行脚本。所以,nGrinder的一大优点就是能够经过使用java的包来扩展,在脚本里面调用java里面的方法来测试某些特殊的应用。 sql
下面就使用这种方式,来使用nGrinder来对数据库进行压力测试。 数据库
首先,来建立脚本。在脚本页面,点击建立脚本: 服务器
输入脚本名,不须要输入url,选上下面的选项,他会帮咱们建立lib目录,脚本执行过程当中使用的扩展包就须要放在lib目录下,若是有其余资源,例如properties文件等,就放在resources目录下。 多线程
点击建立,它会帮咱们使用http测试的模板,建立一个简单的脚本,咱们按照下面直接修改这个脚本: 并发
# -*- coding:utf-8 -*- # Database test. # from java.sql import DriverManager from net.grinder.script.Grinder import grinder from net.grinder.script import Test from cubrid.jdbc.driver import CUBRIDDriver from java.util import Random from java.lang import System test1 = Test(1, "Database insert") test2 = Test(2, "Database update") random = Random(long(System.nanoTime())) # Load the JDBC driver. DriverManager.registerDriver(CUBRIDDriver()) def getConnection(): return DriverManager.getConnection("jdbc:CUBRID:localhost:33000:ngrinder_cluster:::?charset=utf-8", "user", "password") def ensureClosed(object): try: object.close() except: pass # One time initialization that cleans out old data. connection = getConnection() statement = connection.createStatement() # initialize the table should want to test. statement.execute("drop table if exists ngrinder_update_temp") statement.execute("create table ngrinder_update_temp(testid integer, test_number integer)") ensureClosed(statement) ensureClosed(connection) class TestRunner: def __call__(self): connection = None updateStatement = None insertStatement = None try: # in this test, we will create connection and statement in every test transaction. connection = getConnection() updateStatement = connection.createStatement() insertStatement = connection.createStatement() insertStatement = test1.wrap(insertStatement) tmpId = random.nextInt(1024000) insertStatement.execute("insert into ngrinder_update_temp values(%d, %d)" % (tmpId, random.nextInt(1024000))) updateStatement = test2.wrap(updateStatement) updateStatement.execute("update ngrinder_update_temp set test_number=%d where testid=%d" % (random.nextInt(1024000), tmpId)) finally: ensureClosed(updateStatement) ensureClosed(insertStatement) ensureClosed(connection)
在上面的脚本里,咱们先初始化,而后在每次执行时从新获取connection,建立statement,执行2个sql,而后关闭connection和statement。 其中,__call__方法就是要反复执行的方法,它里面有2个test,也就是说,。每执行一次这个方法,而且两个test都执行成功,那么执行的事物的次数就增长2.每秒钟,执行引擎都会统计这一秒执行成功的事物,来统计tps。 dom
在保存以前,能够点击上面的“Validate”来验证脚本是否正确。注意Python须要正确的缩进来保证语法正确,复制过程当中,可能会有缩进的问题。验证完之后,别忘记保存,验证过程当中是不会保存脚本的。 高并发
若是Validate验证结果显示找不到数据库的driver,那就能够保存脚本,而后先上传数据库的JDBC驱动. 性能
打开script列表,在刚才建立的脚本的同级目录中,找到lib进入,而后点击上传按钮:
选择要测试的数据库的相应的JDBC驱动包之后,上传,就能够在lib目录里看到.
再次打开刚才是脚本,验证,若是没有别的问题,就应该在下面看到以下的消息:
2013-01-05 11:06:08,622 INFO The Grinder version 3.9.1 2013-01-05 11:06:08,628 INFO Java(TM) SE Runtime Environment 1.6.0_38-b05: Java HotSpot(TM) 64-Bit Server VM (20.13-b02, mixed mode) on Linux amd64 2.6.18-238.el5 2013-01-05 11:06:08,633 INFO time zone is CST (+0800) 2013-01-05 11:06:08,749 INFO worker process 0 2013-01-05 11:06:08,916 INFO instrumentation agents: traditional Jython instrumenter; byte code transforming instrumenter for Java 2013-01-05 11:06:13,335 INFO running "jdbs-test.py" using Jython 2.2.1 2013-01-05 11:06:13,358 INFO starting, will do 1 run 2013-01-05 11:06:13,359 INFO start time is 1357355173359 ms since Epoch 2013-01-05 11:06:13,410 INFO finished 1 run 2013-01-05 11:06:13,412 INFO elapsed time is 53 ms 2013-01-05 11:06:13,412 INFO Final statistics for this process: 2013-01-05 11:06:13,423 INFO Tests Errors Mean Test Test Time TPS Time (ms) Standard Deviation (ms) Test 1 1 0 3.00 0.00 18.87 "Database insert" Test 2 2 0 0.50 0.50 37.74 "Database update" Totals 3 0 1.33 1.25 56.60 Tests resulting in error only contribute to the Errors column. Statistics for individual tests can be found in the data file, including (possibly incomplete) statistics for erroneous tests. Composite tests are marked with () and not included in the totals. 2013-01-05 11:06:13,347 INFO validation-0: starting threads 2013-01-05 11:06:13,423 INFO validation-0: finished
3)而后,打开test列表页面使用这个脚本建立一个test:
最好在Target Host里面添加数据库所在的机器做为监控目标,这样就能在Report页面看到这台服务器的监控信息。固然,你须要在那台机器上运行Monitor。
4)点击保存并运行。下面就是运行过程当中的监控页面。因为,咱们每次都从新链接,再加上测试的DB已经有应用在运行,因此TPS很是低。MTT(平静测试时间)也接近半秒。
下面详细report页面。
如何提升TPS? 上面的测试中,每次都会从新链接,下面再修改脚本,在测试中都使用一开始的connection进行测试。
# -*- coding:utf-8 -*- # Database test. # from java.sql import DriverManager from net.grinder.script.Grinder import grinder from net.grinder.script import Test from cubrid.jdbc.driver import CUBRIDDriver from java.util import Random from java.lang import System test1 = Test(1, "Database insert") test2 = Test(2, "Database update") random = Random(long(System.nanoTime())) # Load the JDBC driver. DriverManager.registerDriver(CUBRIDDriver()) def getConnection(): return DriverManager.getConnection("jdbc:CUBRID:localhost:33000:ngrinder_cluster:::?charset=utf-8", "user", "password") def ensureClosed(object): try: object.close() except: pass # One time initialization that cleans out old data. connection = getConnection() statement = connection.createStatement() # initialize the table should want to test. statement.execute("drop table if exists ngrinder_update_temp") statement.execute("create table ngrinder_update_temp(testid integer, test_number integer)") ensureClosed(statement) #ensureClosed(connection) class TestRunner: def __call__(self): #connection = None #updateStatement = None #insertStatement = None try: # in this test, we will create connection and statement in every test transaction. # connection = getConnection() updateStatement = connection.createStatement() insertStatement = connection.createStatement() insertStatement = test1.wrap(insertStatement) tmpId = random.nextInt(1024000) insertStatement.execute("insert into ngrinder_update_temp values(%d, %d)" % (tmpId, random.nextInt(1024000))) updateStatement = test2.wrap(updateStatement) updateStatement.execute("update ngrinder_update_temp set test_number=%d where testid=%d" % (random.nextInt(1024000), tmpId)) finally: ensureClosed(updateStatement) ensureClosed(insertStatement) # ensureClosed(connection)
下面是Report,结果就比刚才好不少。
这个例子中,使用JDBC的Jar包来扩展,达到测试的目的。基于这种方法,也可使用任意的其余Jar来扩展,根据具体须要进行各类性能测试。