【轉】使用nGrinder進行數據庫性能測試

原文地址: 使用ngrinder進行數據庫性能測試  java

nGrinder是一個開源的性能測試系統,項目主頁:http://www.nhnopensource.org/ngrinder/。 python

nGrinder是將python腳本部署到多臺agent機器,而後根據配置使用多進程多線程執行,達到高併發的測試目的。agent端使用jython來執行腳本。所以,nGrinder的一大優點就是能夠經過使用java的包來擴展,在腳本里面調用java裏面的方法來測試某些特殊的應用。 sql

下面就使用這種方式,來使用nGrinder來對數據庫進行壓力測試。 數據庫

首先,來建立腳本。在腳本頁面,點擊建立腳本: 服務器

image

輸入腳本名,不須要輸入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進入,而後點擊上傳按鈕:

image

選擇要測試的數據庫的相應的JDBC驅動包之後,上傳,就能夠在lib目錄裏看到.

image

 再次打開剛纔是腳本,驗證,若是沒有別的問題,就應該在下面看到以下的消息:

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:

image

最好在Target Host裏面添加數據庫所在的機器做爲監控目標,這樣就能在Report頁面看到這臺服務器的監控信息。固然,你須要在那臺機器上運行Monitor。

4)點擊保存並運行。下面就是運行過程當中的監控頁面。因爲,咱們每次都從新鏈接,再加上測試的DB已經有應用在運行,因此TPS很是低。MTT(平靜測試時間)也接近半秒。

image

下面詳細report頁面。

image

如何提升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,結果就比剛纔好不少。

image

這個例子中,使用JDBC的Jar包來擴展,達到測試的目的。基於這種方法,也可使用任意的其餘Jar來擴展,根據具體須要進行各類性能測試。

相關文章
相關標籤/搜索