作者:黄炎帝
前言
咱们能否绕开 http 协议,直接测验数据库的功能?是否觉得从数据库中导出 CSV 文件来结构压测数据很麻烦?怎样在压测结束后做数据整理?能不能经过数据库中的刺进(删除)记载对压测恳求做断语?运用阿里云功能测验工具 PTS 能够轻松处理上述问题。
什么是 JDBC
JDBC(Java DataBase Connectivity,Java 数据库衔接)是一种用于履行 SQL 句子的 Java API,可认为多种关系数据库提供一致访问,它由一组用 Java 言语编写的类和接口组成。JDBC 提供了一种基准,据此能够构建更高档的工具和接口,使数据库开发人员能够编写数据库运用程序。
简单地说,JDBC 可做三件事:与数据库树立衔接、发送操作数据库的句子并处理成果。
JDBC 的规划原理
全体架构
JDBC 制定了一套和数据库进行交互的规范,数据库厂商提供这套规范的完成,这样就能够经过一致的 JDBC 接口来衔接各种不同的数据库。能够说 JDBC 的作用是屏蔽了底层数据库的差异,使得用户按照 JDBC 写的代码能够在各种不同的数据库上进行履行。那么这是怎样完成的呢?如下图所示:
JDBC 界说了 Driver 接口,这个接口便是数据库的驱动程序, 一切跟数据库打交道的操作最终都会归结到这里 ,数据库厂商有必要完成该接口,经过这个接口来完成上层运用的调用者和底层详细的数据库进行交互。Driver 是经过 JDBC 提供的 DriverManager 进行注册的,注册的代码写在了 Driver 的静态块中,如 MySQL 的注册代码如下所示:
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
作为驱动界说的规范 Driver,它的首要目的便是和数据库树立衔接,所以其接口也很简单,如下所示:
public interface Driver {
//树立衔接
Connection connect(String url, java.util.Properties info)
throws SQLException;
boolean acceptsURL(String url) throws SQLException;
DriverPropertyInfo[] getPropertyInfo(String url, java.util.Properties info)
throws SQLException;
int getMajorVersion();
int getMinorVersion();
boolean jdbcCompliant();
public Logger getParentLogger() throws SQLFeatureNotSupportedException;
}
作为 Driver 的管理者 DriverManager,它不仅担任 Driver 的注册/注销,还能够直接获取衔接。它是怎样做到的呢?调查下面代码发现,实际是经过遍历所以已经注册的 Driver,找到一个能够成功树立衔接的 Driver,并且将 Connection 返回,DriverManager 就像署理相同,将真实树立衔接的进程仍是交给了详细的 Driver。
for(DriverInfo aDriver : registeredDrivers) {
// If the caller does not have permission to load the driver then
// skip it.
if(isDriverAllowed(aDriver.driver, callerCL)) {
try {
println(" trying " + aDriver.driver.getClass().getName());
Connection con = aDriver.driver.connect(url, info);
if (con != null) {
// Success!
println("getConnection returning " + aDriver.driver.getClass().getName());
return (con);
}
} catch (SQLException ex) {
if (reason == null) {
reason = ex;
}
}
} else {
println(" skipping: " + aDriver.getClass().getName());
}
}
Connection 规划
经过上节咱们知道数据库提供商经过完成Driver接口来向用户提供服务,Driver接口的中心办法便是获取衔接。Connection是和数据库打交道的中心接口,下面咱们看看它的规划方案。
经过调查规划图咱们发现首要有两类接口:DataSource 和 Connection。下面咱们逐个进行介绍。
- DataSource
直接看源码,如下所示,发现它的中心办法居然和 Driver 相同,也是获取衔接。那为什么还要 DataSource 呢?Driver 自身不便是获取衔接的吗?下面咱们就看看 DataSource 到底是怎样获取衔接的。
public interface DataSource extends CommonDataSource, Wrapper {
Connection getConnection() throws SQLException;
Connection getConnection(String username, String password)
throws SQLException;
}
但是咱们发现 JDBC 只界说了 DataSource 的接口,并没有给出详细完成,下面咱们就以 Spring 完成的 SimpleDriverDataSource 为例,来看看它是怎样做的,代码如下所示,发现 DataSource 的 getConnection(…)办法,最终居然仍是交由 driver.connect(…)去真实树立衔接。所以又回到最开端咱们所描述的, Driver 才是真实的与数据库打交道的接口。
protected Connection getConnectionFromDriver(Properties props) throws SQLException {
Driver driver = getDriver();
String url = getUrl();
Assert.notNull(driver, "Driver must not be null");
if (logger.isDebugEnabled()) {
logger.debug("Creating new JDBC Driver Connection to [" + url + "]");
}
return driver.connect(url, props);
}
那么问题来了,为什么还需求 DataSource 这样的接口,岂不多此一举么?明显不会。DataSource 是加强版的 Driver。它将中心的树立衔接的进程交由 Driver 履行,而关于树立缓存,处理分布式事务和衔接池等看似与树立衔接无关的事情自己来处理。如类的规划图所示,以 PTS 运用的 Druid 衔接池为例:
-
ConnectionPoolDataSource:衔接池的完成,此数据源完成并不直接创立数据库物理衔接,而是一个逻辑完成,它的作用在于池化数据库物理衔接。
-
PooledConnection:合作 ConnectionPoolDataSource,由它获取一个池化对象 PooledConnection,再经过该 PooledConnection 直接获取到物理衔接。
明显,经过衔接池咱们能够从衔接的管理中脱身,进步衔接的运用功率,也能提升压力机的施压才能。
Statement 规划
树立衔接之后,用户可能要开端写 SQL 句子,并且交由数据库去履行了。这些是经过 Statement 来完成的。首要分为:
-
Statement:界说一个静态的 SQL 句子,数据库每次履行都需求从头编译,一般用于仅履行一次查询并返回成果的景象。
-
PreparedStatement:界说一个带参的预编译的 SQL 句子,下次履行时,会从缓存中取出遍以后的句子,而不需求从头编译一遍,适用于履行屡次相同逻辑的 SQL 句子,当然它还有防 SQL 注入等功能,安全性和功率较高,运用比较频频。关于功能测验来说,挑选 PreparedStatement 最为合适。
-
CallableStatement:用来调用存储进程。
ResultSet 规划
JDBC 运用 ResultSet 接口来承接 Statement 的履行成果。ResultSet 运用指针的方法(next())来逐条获取检索成果,当指针指向某条数据时,用户能够自在的挑选获取某一列的数据。PTS 经过将 ResultSet 转化成 CSV 文件,辅助用户以一条 SQL 句子,结构复杂的压测数据。
JDBC 架构总结
经过上面的介绍咱们发现,JDBC 的规划仍是层次感分明的。
(1)Driver 和 DriverManager 是面向数据库的,规划了一套 Java 访问数据的规范,数据库厂商只需求完成这套规范即可;
(2)DataSource 和 Connection 是面向运用程序开发者的,它们不关心 JDBC 详细是怎样跟数据库进行交互的,经过一致的 DataSource 接口就能够拿到 Connection,用户的数据操作都能够经过这个 Connection 来完成了;
(3)Statement 承载了详细的 SQL 指令,用户能够界说不同的 Statement 来向数据库发送指令;
(4)ResultSet 是用来承载 SQL 指令的履行成果。
至此,完成了 加载驱动 -> 树立衔接 -> 履行指令 -> 返回成果 这样的和数据库交互的整个进程。如果把这个进程灵活的嵌入到 PTS 功能测验中,便能够处理前言提到的各种问题。
JDBC 在功能测验中的运用
数据库功能测验
- 背景
大多数对数据库的操作都是经过 HTTP、FTP 或其他协议履行的,但是在某些情况下,绕开中间协议直接测验数据库也很有含义。例如咱们希望不触发一切相关查询,而只测验特定 high-value 查询的功能;验证新数据库在高负载下的功能。2.验证某些数据库衔接池参数,例如最大衔接数 3.节省时间和资源。当咱们想要优化 SQL 时,修正代码中的 SQL 句子和其他数据库操作十分繁琐,经过 JDBC 压测,咱们能够防止侵入代码,集中精力在 SQL 调优上。
- 过程
1、创立场景。咱们在 PTS 控制台的【压测中心】->【创立场景】中创立 PTS 压测场景;
2、场景配置。PTS 支撑对 MySQL、PostgreSQL 等四种数据库发起压测。用户填写 JDBC URL、用户名、暗码和 SQL 即可发起压测。一起,PTS 还支撑提取 ResultSet 中的数据作为出参,给下流 API 运用;对响应进行断语。
3、压测中监控和压测陈述。PTS 支撑绑定阿里云 RDS 云资源监控,在压测进程中调查 RDS 实时功能指标。此外,PTS 还提供清晰齐备的压测陈述以及采样日志,供用户随时检查。
压测数据结构
- 背景
在模拟不同用户登录、压测事务参数传递等场景中,需求运用参数功能来完成压测的恳求中各种动态操作。如果运用传统的 CSV 文件参数,会遭到文件大小的约束,且手动创立耗费精力。运用 JDBC 来结构压测数据,能够防止以上问题。
- 过程
1、增加数据源。在场景修改-数据源管理中,挑选增加 DB 数据源,输入 URL、用户名、暗码和 SQL。
2、增加参数。填写自界说参数名和列索引。
3、调试验证。点击调试场景,即可验证提取的成果集是否符合预期。接着,咱们就能够在任意想要运用参数的 地方运用${}引用即可。
压测脏数据整理
- 背景
针对写恳求的压测,会在数据库中生成大量脏数据。怎样在压测结束后主动整理?
- 过程
PTS 给用户提供了处理方案。PTS 支撑对串联链路作逻辑上的顺序编列,即前置链路、一般链路和后置链路。履行顺序由先到后。设置某条串联链路为后置链路,填写循环次数即可。
更多沟通,欢迎进钉钉群沟通,PTS 用户沟通钉钉群号:11774967。
此外,PTS 近期对售卖方法做了全新升级,基础版价格直降 50%!5W 并发价格只需 199,免除自运维压测渠道烦恼!更有新用户 0.99 体验版、VPC 压测专属版,欢迎大家选购!