本次测试主要目的是对比 AngusTester 和 JMeter 对 JDBC 协议性能表现。
测试环境
以下测试 AngusTester 和 JMeter 使用相同环境。注意:本次测试是在同一台 PC 机上进行,如果想测试特定配置下数据库的准确性能,需要将测试机和 MySQL服务器分开部署,或者使用更高配置的测试服务器。
软件
-
数据库 :Percona Server MySQL 5.7.34-37
-
MySQL 驱动:mysql-connector-j-8.0.31.jar
-
Docker :19.03.11 (使用 Docker 部署 MySQL)
-
测试工具
- AngusTester 1.0.0
- Apache JMeter 4.0
系统
MacBookPro16 PC
- Processors: 1
- Cores: 8 * 2 Intel Core i9 2.3 GHz
- Memory: 32 GB
MySQL 配置
character_set_server = utf8mb4
skip-host-cache
skip-name-resolve
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
secure-file-priv=/var/lib/mysql-files
user=mysql
max_allowed_packet=100M
max_connections=2000 # 最大连接数
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
log-error=/var/log/mysql/error.log
pid-file=/var/run/mysqld/mysqld.pid
测试表
CREATE TABLE `user` (
`username` varchar(255) NOT NULL,
`password` varchar(255) NULL DEFAULT NULL,
INDEX `idx_username`(`username`) USING BTREE
) ENGINE = InnoDB;
测试脚本
- JMeter Insert 脚本 (JDBC_Testing_Insert_AngusTesterVSJMeter.jmx)
<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="4.0" jmeter="4.0 r1823414">
<hashTree>
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Jdbc prepared update performance testing" enabled="true">
<stringProp name="TestPlan.comments"></stringProp>
<boolProp name="TestPlan.functional_mode">false</boolProp>
<boolProp name="TestPlan.tearDown_on_shutdown">true</boolProp>
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="TestPlan.user_define_classpath"></stringProp>
</TestPlan>
<hashTree>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group" enabled="true">
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
<boolProp name="LoopController.continue_forever">false</boolProp>
<intProp name="LoopController.loops">-1</intProp>
</elementProp>
<stringProp name="ThreadGroup.num_threads">1<!-- 1/10/50/100/200/500/1000/2000 --></stringProp>
<stringProp name="ThreadGroup.ramp_time"></stringProp>
<boolProp name="ThreadGroup.scheduler">true</boolProp>
<stringProp name="ThreadGroup.duration">60</stringProp>
<stringProp name="ThreadGroup.delay"></stringProp>
</ThreadGroup>
<hashTree>
<JDBCDataSource guiclass="TestBeanGUI" testclass="JDBCDataSource" testname="JDBC Connection Configuration" enabled="true">
<boolProp name="autocommit">true</boolProp>
<stringProp name="checkQuery"></stringProp>
<stringProp name="connectionAge">5000</stringProp>
<stringProp name="dataSource">test</stringProp>
<stringProp name="dbUrl">jdbc:mysql://localhost:3306/xcan_mockdata_sample</stringProp>
<stringProp name="driver">com.mysql.cj.jdbc.Driver</stringProp>
<boolProp name="keepAlive">true</boolProp>
<stringProp name="password">123456</stringProp>
<stringProp name="poolMax">0</stringProp>
<stringProp name="timeout">100000</stringProp>
<stringProp name="transactionIsolation">DEFAULT</stringProp>
<stringProp name="trimInterval">200000</stringProp>
<stringProp name="username">sample</stringProp>
</JDBCDataSource>
<hashTree/>
<JDBCSampler guiclass="TestBeanGUI" testclass="JDBCSampler" testname="JDBC Request" enabled="true">
<stringProp name="dataSource">test</stringProp>
<stringProp name="query">INSERT INTO `user` (username, password) VALUES (?, ?)</stringProp>
<stringProp name="queryArguments">${__RandomString(16,0123456789abcdefghijklmnopqrstuvwxyz,)},${__RandomString(32,0123456789abcdefghijklmnopqrstuvwxyz,)}</stringProp>
<stringProp name="queryArgumentsTypes">VARCHAR,VARCHAR</stringProp>
<stringProp name="queryTimeout">60</stringProp>
<stringProp name="queryType">Prepared Update Statement</stringProp>
<stringProp name="resultSetHandler">Store as String</stringProp>
<stringProp name="resultVariable"></stringProp>
<stringProp name="variableNames"></stringProp>
</JDBCSampler>
<hashTree/>
</hashTree>
</hashTree>
</hashTree>
</jmeterTestPlan>
运行脚本:
./jmeter -n -t ~/scripts/JDBC_Testing_Insert_AngusTesterVSJMeter.jmx
- AngusTester Insert 脚本 (JDBC_Testing_Insert_AngusTesterVSJMeter.yaml)
specification: angus/1.0.0
info:
name: Jdbc prepared update performance testing
description: This is an example of jdbc insert statement testing.
type: TEST_PERFORMANCE
plugin: Jdbc
configuration:
duration: 60s
thread:
threads: 1 # 1/10/50/100/200/500/1000/2000
priority: 1000
task:
arguments:
jdbcSetting:
type: MYSQL
driverClassName: com.mysql.cj.jdbc.Driver
jdbcUrl: jdbc:mysql://localhost:3306/xcan_mockdata_sample
username: sample
password: 123456
ignoreAssertions: true
pipelines:
- target: JDBC
name: UpdateUser
description: Save user by prepared update statement
enabled: true
type: PREPARED_UPDATE
sql: "INSERT INTO `user` (username, password) VALUES (?, ?)"
timeoutInSecond: 60
arguments:
- type: varchar
value: "@String(16)" # Mock数据函数
inout: IN
- type: varchar
value: "@String(32)" # Mock数据函数
inout: IN
运行脚本:
./startup-runner.sh -s ~/scripts/JDBC_Testing_Insert_AngusTesterVSJMeter.yaml -e 1001
- JMeter Select 脚本 (JDBC_Testing_Select_AngusTesterVSJMeter.jmx)
<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="4.0" jmeter="4.0 r1823414">
<hashTree>
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Jdbc prepared select performance testing" enabled="true">
<stringProp name="TestPlan.comments"></stringProp>
<boolProp name="TestPlan.functional_mode">false</boolProp>
<boolProp name="TestPlan.tearDown_on_shutdown">true</boolProp>
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="TestPlan.user_define_classpath"></stringProp>
</TestPlan>
<hashTree>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group" enabled="true">
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
<boolProp name="LoopController.continue_forever">false</boolProp>
<intProp name="LoopController.loops">-1</intProp>
</elementProp>
<stringProp name="ThreadGroup.num_threads">1<!-- 1/10/50/100/200/500/1000/2000 --></stringProp>
<stringProp name="ThreadGroup.ramp_time"></stringProp>
<boolProp name="ThreadGroup.scheduler">true</boolProp>
<stringProp name="ThreadGroup.duration">60</stringProp>
<stringProp name="ThreadGroup.delay"></stringProp>
</ThreadGroup>
<hashTree>
<JDBCDataSource guiclass="TestBeanGUI" testclass="JDBCDataSource" testname="JDBC Connection Configuration" enabled="true">
<boolProp name="autocommit">true</boolProp>
<stringProp name="checkQuery"></stringProp>
<stringProp name="connectionAge">5000</stringProp>
<stringProp name="dataSource">test</stringProp>
<stringProp name="dbUrl">jdbc:mysql://localhost:3306/xcan_mockdata_sample</stringProp>
<stringProp name="driver">com.mysql.cj.jdbc.Driver</stringProp>
<boolProp name="keepAlive">true</boolProp>
<stringProp name="password">123456</stringProp>
<stringProp name="poolMax">0</stringProp>
<stringProp name="timeout">100000</stringProp>
<stringProp name="transactionIsolation">DEFAULT</stringProp>
<stringProp name="trimInterval">200000</stringProp>
<stringProp name="username">sample</stringProp>
</JDBCDataSource>
<hashTree/>
<JDBCSampler guiclass="TestBeanGUI" testclass="JDBCSampler" testname="JDBC Request" enabled="true">
<stringProp name="dataSource"&