背景
上一篇《数据源连接池未关闭的问题 Could not open JDBC Connection for transaction》分析源码了解了MyBatis框架和Spring事务管理自动关闭数据源连接池的功能,解决了一个线上数据源连接池占满的问题。
但解决了一个可能还有下一个,现在需要一个能监控数据源连接池使用情况、快占满了报警的方案。
方案一
这里使用的是Druid数据源,其他数据源可以使用下面的方案二。
Druid数据源本身有一个filter,在获取数据源连接(调用getConnection方法)时会依次调用所有的filter。
于是乎,我们就可以在数据源初始化时增加一个filter,用于查看当前连接池的情况,代码如下:
List<Filter> filters = new ArrayList<Filter>();
filters.add(new FilterAdapter(){
@Override
public DruidPooledConnection dataSource_getConnection(FilterChain chain, DruidDataSource dataSource, long maxWaitMillis) throws SQLException {
int activeCount = dataSource.getActiveCount();
if (activeCount > (dataSource.getMaxActive() * 0.8)) {
log.error("Druid Warning,the current active count of Druid Connection Pool is " + activeCount + "!");
}
return chain.dataSource_connect(dataSource, maxWaitMillis);
}
});
dataSource.setProxyFilters(filters);
这里当当前连接数大于最大连接数的80%会打印错误日志,当然也可以再次增加其他各种报警代码。
方案二
方案二可以应用在一般的数据源,不限定Druid数据源。核心思想为,写一个继承数据源子类,重写获取连接的方法,在获取连接前实现监控的代码,示例代码如下:
DruidDataSource dataSource = new DruidDataSource(){
protected Logger log = LoggerFactory.getLogger(BaqiDataSource.class);
@Override
public DruidPooledConnection getConnectionDirect(long maxWaitMillis) throws SQLException {
int activeCount = this.getActiveCount();
if (activeCount > (dataSource.getMaxActive() * 0.8)) {
log.error("Druid Warning,the current active count of Druid Connection Pool is " + activeCount + "!");
}
return super.getConnectionDirect(maxWaitMillis);
}
};
//以下初始化连接池
dataSource.setUrl("xxx");
dataSource.setUsername("xxx");
dataSource.setPassword("xxx"));
dataSource.setDriverClassName("xxx"));
...
结论
方案一适用于Druid数据源,方案二适用于所有的数据源,可以根据情况使用。