【转】使用nGrinder进行数据库性能测试

原文地址: 使用ngrinder进行数据库性能测试 

nGrinder是一个开源的性能测试系统,项目主页:http://www.nhnopensource.org/ngrinder/。

nGrinder是将python脚本部署到多台agent机器,然后根据配置使用多进程多线程执行,达到高并发的测试目的。agent端使用jython来执行脚本。因此,nGrinder的一大优势就是可以通过使用java的包来扩展,在脚本里面调用java里面的方法来测试某些特殊的应用。

下面就使用这种方式,来使用nGrinder来对数据库进行压力测试。

首先,来创建脚本。在脚本页面,点击创建脚本:

【转】使用nGrinder进行数据库性能测试_第1张图片

输入脚本名,不需要输入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。

   在保存之前,可以点击上面的“Validate”来验证脚本是否正确。注意Python需要正确的缩进来保证语法正确,复制过程中,可能会有缩进的问题。验证完以后,别忘记保存,验证过程中是不会保存脚本的。

   如果Validate验证结果显示找不到数据库的driver,那就可以保存脚本,然后先上传数据库的JDBC驱动.

   打开script列表,在刚才创建的脚本的同级目录中,找到lib进入,然后点击上传按钮:

【转】使用nGrinder进行数据库性能测试_第2张图片

选择要测试的数据库的相应的JDBC驱动包以后,上传,就可以在lib目录里看到.

【转】使用nGrinder进行数据库性能测试_第3张图片

 再次打开刚才是脚本,验证,如果没有别的问题,就应该在下面看到如下的消息:

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:

【转】使用nGrinder进行数据库性能测试_第4张图片

最好在Target Host里面添加数据库所在的机器作为监控目标,这样就能在Report页面看到这台服务器的监控信息。当然,你需要在那台机器上运行Monitor。

4)点击保存并运行。下面就是运行过程中的监控页面。由于,我们每次都重新连接,再加上测试的DB已经有应用在运行,所以TPS非常低。MTT(平静测试时间)也接近半秒。

【转】使用nGrinder进行数据库性能测试_第5张图片

下面详细report页面。

【转】使用nGrinder进行数据库性能测试_第6张图片

如何提高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,结果就比刚才好很多。

【转】使用nGrinder进行数据库性能测试_第7张图片

这个例子中,使用JDBC的Jar包来扩展,达到测试的目的。基于这种方法,也可以使用任意的其他Jar来扩展,根据具体需要进行各种性能测试。

你可能感兴趣的:(数据库,jdbc,性能测试,nGrinder)