tomcat 数据连接池问题分析
- 关联笔记(本地):【Java 自带性能监控工具:监视和管理控制台 jconsole 的使用/java监视和管理控制台】
- 关联博客:Druid java.sql.SQLException: 违反协议 / Oracle连接报错生违反协议
1. 生产现象
- 数据库锁表,且为不同表出现锁表
- 服务线程监控,达到最大连接数40
2. 排查步骤
2.1 查看服务器tomcat配置
- server.xml http 允许最大线程数为40
<Connector port="8888" protocol="HTTP/1.1"
maxThreads="40" minSpareThreads="2" acceptCount="100"
connectionTimeout="20000" redirectPort="8443" URIEncoding="GBK" relaxedPathChars="|{}[]^,"
relaxedQueryChars="|{}[]^,"/>
- context.xml共配置5个数据源,核心系统主要使用的数据源,配置空闲连接数maxIdle=“8”,
最大连接数maxTotal="40"
<Resource auth="Container"
driverClassName="oracle.jdbc.OracleDriver"
maxIdle="8" maxTotal="40" name="xxxDataSource"
type="javax.sql.DataSource">
</Resource>
2.2 分析线程信息
-
kill -3 pid 输出堆栈信息
-
tomcat默认堆栈信息输出在catalina.out,在日志文件中找到对应堆栈输出信息,如下
-
分析堆栈信息,发现堵塞的线程,报错信息都在等待数据源,推断tomcat配置数据源不够应用程序使用,因此出现线程等待情况,如下图
但根据tomcat最大连接数 maxTotal="40"
,系统应该不会频繁的造成数据连接数耗尽,所以按照两个方向处理:
- a) 分析代码程序,针对于一次请求中,嵌套开启数据源的程序进行修改;
- b) 继续dump进行分析
2.3 继续对dump文件进行分析
服务器上,使用命令生成日志文件,生成文件heapdump.phrof,将文件copy到本地,使用jvisualvm工具进行分析
jmap -dump:live,format=b,file=heapdump.phrof pid
打开jdk1.8 自带工具\jdk1.8\bin\jvisualvm.exe
文件–>装入–>选择对应dump文件
执行OQL脚本,查看结果
执行脚本
select map(heap.objects("org.apache.tomcat.dbcp.dbcp2.PoolingDataSource"),
"'<ul>' + it._pool.oname._canonicalName.value.toString()
+ '<li> idleCount:' + it._pool.idleObjects.count + '</li>'
+ '<li> maxTotal:' + it._pool.maxTotal + '</li>'
+ '<li> createdCount:' + it._pool.createdCount.value + '</li>'
+ '<li> borrowedCount:' + it._pool.borrowedCount.value + '</li>'
+ '<li> returnedCount:' + it._pool.returnedCount.value + '</li>'
+ '<li> inUsed:' + (it._pool.borrowedCount.value - it._pool.returnedCount.value) + '</li>'
+ '</ul>'");
- 查看到结果,
maxTotal 实际值为8,与配置的不同
- 再次分析context.xml中的数据源配置,发现数据库的密码做过加密,找到之前做加密功能时,新增了tomcat-dbcp.jar,怀疑此jar包对数据源配置参数有影响
- 修改context.xml 最大连接数的配置参数为 maxActive="40" 再此进行验证。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CWhVmryx-1577252352337)(en-resource://database/4518:1)]
系统修改方案
- 临时方案:生产已经更新数据库密码加密的服务,暂时context.xml中最大连接数配置参数调整为:
maxActive="40"
- 后续调整方案,调整durid数据连接池,并通过升级前需要进行验证,查看dump文件中,实际生效的数据连接参数与配置值是否一致。同时进行压力测试。