大型商业银行数据库连接池选型策略
作者介绍
张馨鹏,某大型商业银行研发中心中级工程师,主要负责数据库、操作系统等基础组件的测评工作。
一、前言
应用程序访问与操作数据库,需要与数据库建立一条连接。但建立数据库连接是一个比较消耗时间和资源的过程。尤其在多并发访问时,会造成数据库连接频繁的创建与关闭,导致程序性能急剧下降,严重时可以造成应用程序崩溃。目前最常用的解决方案是使用数据库连接池管理数据库连接。
数据库连接池是数据库连接对象的缓存技术,负责分配、管理、释放数据库连接。应用程序在启动时创建指定数量的数据库连接组成数据库连接池,由应用程序动态的对池中的连接进行复用、增加和释放。连接池技术避免了重复创建和关闭数据库连接带来的消耗,极大的复用了内存资源,从而提高了程序的运行效率。
二、数据库连接池测试
我司因数据库连接池的选择和使用方式的不同出现过一些问题。一般数据库连接池正确的使用方式是一个线程从连接池中取得连接后,待使用完毕后关闭连接。某项目组在使用Druid连接池时,从连接池中取得连接后,使用多线程去访问该连接,造成交易异常报错。显然这种使用方式不是推荐使用的。
当前我司开放系统端主要运行于JVM和.Net两类环境,主要使用Oracle和主机DB2两种数据库。使用的数据库连接池包括JNDI、Druid、Tomcat、Oracle UCP等。面对行内众多的数据库连接池,抛开使用方式的问题,是否存在多线程访问安全问题?是否存在较大的性能差异?以及我们该如何选择一款数据库连接池?
验证行内常用数据库连接池是否有多线程访问安全问题。
对比行内常用数据库连接池的性能差异。
Druid连接池:由阿里巴巴开源,我司自研框架测试环境使用的连接池。
JNDI连接池:由J2EE提供,WebSphere环境使用的连接池。
Tomcat连接池:广泛使用的开源数据库连接池。
UCP连接池:由Oracle开发并提供技术支持的数据库连接池。
服务器:JWS服务器、Tomcat服务器、WebSphere服务器。
数据库:Oracle 12.0.0.12、Oracle 19C。
在多服务器、多数据库环境下使用性能测试工具Jmeter进行压力测试。
1)编写测试程序
编写Java web程序,主要功能包括:多种数据库连接池配置、多线程访问连接池连接、数据库增删改查。连接池均设置为初始连接为10,最小连接为10,最大连接为100,不做其他参数配置。
2)环境部署
完成数据库Oracle12c RAC、Oracle19c RAC安装部署,应用服务器方面在SUSE 12完成WebSphere安装部署,在RHEL 7.5完成Tomcat 9部署,基于我司容器平台完成JWS部署。应用服务器和容器使用的虚拟机配置均为2核8G。
▲ 表1:测试环境
3)性能测试
使用Jmeter作为性能测试工具,分别开启20、40、80、160线程对应用程序访问连接进行压力测试,测试持续时间120秒(含启动时间)。记录测试期间应用服务器所在操作系统的CPU、内存使用率。测试结束后记录Jmeter TPS。
▲ 图1:Jmeter线程与时间设置
▲ 图2:Jmeter HTTP请求设置
4)多线程访问安全测试
测试环境与性能测试保持一致,分别开启2、4、8、16线程对应用程序多线程对连接池中一个连接进行压力测试。每种并发下重复测试3-5次,观察程序异常报错。如有报错则关闭测试,即视为多线程访问不安全。
应用服务器Tomcat 9下连接池性能测试如下:
▲ 表2:Tomcat服务器下测试结果
应用服务器Websphere下连接池性能测试结果如下:
▲ 表3:Websphere服务器下测试结果
基于PAAS平台JWS服务器下连接池性能测试结果如下:
▲ 表4:JWS服务器下性能测试结果
▲ 表5:多线程访问安全测试
通过性能测试数据可以看出,线程数越大TPS越高,但线程完成时间也越长,同时线程争抢以及等待也会增大。在相同的测试条件下,连接池Druid的CPU使用率略高。通过TPS可以看出,这四款数据库连接池并无较大的性能差异。
线程安全方面,Oracle UCP和Tomcat连接池全无异常,Druid和JNDI大部分场景均出现异常。其中Tomcat属于开源产品。UCP连接池是由Oracle官方开发提供,Oracle官方承诺UCP连接池相关服务在原厂维保内。因此,在采购Oracle原厂服务的情况下,推荐使用Oracle数据库连接池UCP。
三、正确使用数据库连接池
数据库连接池的工作过程大致如下:
1)连接池建立
应用程序启动,根据连接池配置的最小连接数,创建此数目的数据库连接放到连接池中。
2)连接池使用
应用需要访问数据库时,首先检查数据库连接池中是否有空闲连接,如果存在空闲连接,则将分配空闲连接给应用使用。如果没有空闲连接,则会检查连接池中已经使用的连接是否已经达到最大连接数,如果没达到就创建一个新的连接给应用,如果连接数已经达到最大连接数就按照设定好的最大等待时间进行等待连接释放,如果超出最大等待时间,则抛出异常。
3)连接池释放连接
应用释放数据库连接时,检查连接池是否已经达到最大连接数,如果没有则会保留在连接池中,否则从连接池中删除该连接。
根据以上过程可以看出,数据库连接池是对数据库连接进行复用、增加和释放来避免了重复创建和关闭数据库连接带来的消耗,从而提高了程序的运行效率。在多线程访问下,多线程访问同一连接是不正确使用方式。正确的使用方式是每个线程都在连接池中取用连接,使用完毕归还连接,避免长时间持有连接导致异常。