新考纲-系统架构设计师(软考高级) 一站式通关课程(完结无密)
下载看水印
通过上面的原因分析知道,问题产生的根本原因就是没有对数据库连接数做控制。那解决的方案就是加个连接池呗,然后说到连接池这玩意儿,我之前是真没自己实现过。本着求真务实的态度,怎么着也得试试。
连接池原理
在说连接池以前先说一下对象池。众所周知,Java是一门面向对象的语言,JVM中每时每刻都在创造着新的对象。这其中有一些对象其实没有必要一直重复创建销毁的过程。过日子就得讲究一个精打细算嘛,能重复利用咱就别折腾了。这部分对象给他分配个池子,让它们泡着就行。谁要用拿去用就是,用完记得还回来就行。连接池的原理其实也是这样,我们可以定义好一组数据库连接对象实例,由需要发起数据库连接的线程自己去借用,然后完成对应的数据库操作,这样的话,无论有多少线程需要发起数据库连接,他们能创建的数据库连接的上限都不会超多连接池指定的上限。关于线程等待的问题,就涉及到连接池参数调优的问题了,这里就不讨论了。
基于连接池重写InfluxDB连接组件
连接池的实现我们可以借助Apache Commons Pool来完成。它主要由几个关键接口和类组成。最核心的是ObjectPool接口,它定义了对象池的基本操作,例如借用对象(borrowObject)、返还对象(returnObject)等。然后是PooledObjectFactory接口,这是一个用于创建和管理池对象生命周期的工厂接口。通常,当我们需要将自定义的对象放入对象池时,就需要实现这个接口。说干就干,代码走起
1、 实现PooledObjectFactory,创建一个对象工厂
java复制代码package org.springframework.data.influxdb; import org.apache.commons.pool2.PooledObject; import org.apache.commons.pool2.PooledObjectFactory; import org.apache.commons.pool2.impl.DefaultPooledObject; import org.influxdb.InfluxDB; import org.influxdb.InfluxDBFactory; import org.influxdb.dto.Pong; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Richard */ public class InfluxDBPooledObjectFactory implements PooledObjectFactory<InfluxDB> { private static final Logger logger = LoggerFactory.getLogger(InfluxDBPooledObjectFactory.class); private final InfluxDBProperties properties; public InfluxDBPooledObjectFactory(InfluxDBProperties properties) { this.properties = properties; } /** * 重新初始化要由池返回的实例-即从池中借用一个对象时调用 * * @param pooledObject 一个PooledObject包装要激活的实例 * @throws Exception */ @Override public void activateObject(PooledObject<InfluxDB> pooledObject) throws Exception { logger.debug("InfluxDB connection was borrowed!"); } /** * 使用默认 (NORMAL) DestroyMode 销毁池不再需要的实例。 * * @param pooledObject * @throws Exception */ @Override public void destroyObject(PooledObject<InfluxDB> pooledObject) throws Exception { InfluxDB influxDBClient = pooledObject.getObject(); influxDBClient.close(); } /** * 创建可由池提供服务的实例,并将其包装在由池管理的PooledObject中 * * @return * @throws Exception */ @Override public PooledObject<InfluxDB> makeObject() throws Exception { InfluxDB connection = InfluxDBFactory.connect(properties.getUrl(), properties.getUsername(), properties.getPassword()); if (properties.isGzip()) { connection.enableGzip(); } return new DefaultPooledObject<>(connection); } /** * 取消初始化要返回到空闲对象池的实例-即从池中归还一个对象时调用 * * @param pooledObject * @throws Exception */ @Override public void passivateObject(PooledObject<InfluxDB> pooledObject) throws Exception { logger.debug("InfluxDB connection was returned!"); } /** * 确保实例可以安全地由池返回。 * * @param pooledObject * @return 如果obj无效并且应该从池中删除,则为false ,否则为true */ @Override public boolean validateObject(PooledObject<InfluxDB> pooledObject) { InfluxDB influxDBClient = pooledObject.getObject(); Pong pong = influxDBClient.ping(); return pong.isGood(); } }
领取专属 10元无门槛券
私享最新 技术干货