信阳网站建设,酒店做网站,农村房屋设计图,网站怎么自己做推广前言
我们能否绕开 http 协议#xff0c;直接测试数据库的性能#xff1f;是否觉得从数据库中导出 CSV 文件来构造压测数据很麻烦#xff1f;怎样在压测结束后做数据清理#xff1f;能不能通过数据库中的插入#xff08;删除#xff09;记录对压测请求做断言#xff1f…前言
我们能否绕开 http 协议直接测试数据库的性能是否觉得从数据库中导出 CSV 文件来构造压测数据很麻烦怎样在压测结束后做数据清理能不能通过数据库中的插入删除记录对压测请求做断言使用阿里云性能测试工具 PTS 可以轻松解决上述问题。
什么是 JDBC
JDBCJava DataBase ConnectivityJava 数据库连接是一种用于执行 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(Cant 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 的设计还是层次感分明的。
1Driver 和 DriverManager 是面向数据库的设计了一套 Java 访问数据的规范数据库厂商只需要实现这套规范即可
2DataSource 和 Connection 是面向应用程序开发者的它们不关心 JDBC 具体是如何跟数据库进行交互的通过统一的 DataSource 接口就可以拿到 Connection用户的数据操作都可以通过这个 Connection 来实现了
3Statement 承载了具体的 SQL 命令用户可以定义不同的 Statement 来向数据库发送指令
4ResultSet 是用来承载 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 支持对串联链路作逻辑上的顺序编排即前置链路、普通链路和后置链路。执行顺序由先到后。设置某条串联链路为后置链路填写循环次数即可。 作者黄炎帝
原文链接
本文为阿里云原创内容未经允许不得转载。