參考引用文檔:http://www.reibang.com/p/b45b96a61451
https://blog.csdn.net/qq_37186947/article/details/104227552
書接上文 Java連接influxDB非迹,創(chuàng)建一個(gè)influxDB的連接池后控。
1瑟俭、添加依賴
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.11.1</version>
</dependency>
2、實(shí)現(xiàn)PooledObjectFactory燕锥,創(chuàng)建一個(gè)對(duì)象工廠
需要重寫5個(gè)函數(shù):
makeObject 方法 :用于對(duì)象的新建顽频,一般是 new 出來之后包裝一下菱蔬。而什么時(shí)候需要新建呢,根據(jù)策略不同則時(shí)機(jī)不同砾层。例如在沒有閑置資源對(duì)象漩绵,且已存在的資源數(shù)不超過所設(shè)置的最大資源時(shí)新建。
destroyObject 方法:銷毀一個(gè)對(duì)象肛炮,除了很容易想到的閑置過長(zhǎng)時(shí)間被清理掉了導(dǎo)致需要銷毀之外止吐,還有如果進(jìn)行了第三個(gè)方法且返回了 false ,那么也是需要銷毀的侨糟。
validateObject方法:檢驗(yàn)這個(gè)對(duì)象是否還有有效碍扔,借出和歸還時(shí),以及內(nèi)置后臺(tái)線程檢測(cè)閑置情況時(shí)秕重,可以通過驗(yàn)證可以去除一些不符合業(yè)務(wù)邏輯的資源對(duì)象不同。默認(rèn)這個(gè)方法是不被調(diào)用的,要開啟則需要在PoolConfig中設(shè)置setTestOnBorrow , setTestOnReturn , setTestWhileIdle等屬性溶耘。
activeObject 方法: 在借用一個(gè)對(duì)象的時(shí)候調(diào)用二拐,則可以在此重置其內(nèi)部狀態(tài),那么返回的對(duì)象就像新的一樣
passivateObject 方法: 對(duì)應(yīng) activateObject 方法凳兵,是在歸還一個(gè)對(duì)象的時(shí)候調(diào)用卓鹿,注意不應(yīng)與activateObject方法有業(yè)務(wù)邏輯上的沖突
import com.influxdb.client.InfluxDBClient;
import com.influxdb.client.InfluxDBClientFactory;
import com.influxdb.client.domain.HealthCheck;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;
/**
* @author Jenson
*/
public class InfluxdbPooledObjectFactory implements PooledObjectFactory<InfluxDBClient> {
/**
* 重新初始化要由池返回的實(shí)例-即從池中借用一個(gè)對(duì)象時(shí)調(diào)用
*
* @param pooledObject 一個(gè)PooledObject包裝要激活的實(shí)例
* @throws Exception
*/
@Override
public void activateObject(PooledObject<InfluxDBClient> pooledObject) throws Exception {
System.out.println("重新初始化要由池返回的實(shí)例-即從池中借用一個(gè)對(duì)象時(shí)調(diào)用");
}
/**
* 使用默認(rèn) (NORMAL) DestroyMode 銷毀池不再需要的實(shí)例。
*
* @param pooledObject
* @throws Exception
*/
@Override
public void destroyObject(PooledObject<InfluxDBClient> pooledObject) throws Exception {
InfluxDBClient influxDBClient = pooledObject.getObject();
influxDBClient.close();
}
/**
* 創(chuàng)建可由池提供服務(wù)的實(shí)例留荔,并將其包裝在由池管理的PooledObject中
*
* @return
* @throws Exception
*/
@Override
public PooledObject<InfluxDBClient> makeObject() throws Exception {
// 生成客戶端
// InfluxDBClient client = InfluxDBClientFactory.create(this.url, this.token.toCharArray());
InfluxDBClient client = InfluxDBClientFactory.create("http://127.0.0.1:8086",
"S9dKiPFvnSUd9p406aCkCdwZ_q5rke8mNWzxERaNOL6SW0Fl2JIHZ1V9B317BqmBxzdaFwxei2TcYwJu2RXnOg==".toCharArray());
System.out.println("創(chuàng)建可由池提供服務(wù)的實(shí)例,并將其包裝在由池管理的PooledObject中, hashcode :"+client.hashCode());
return new DefaultPooledObject<>(client);
}
/**
* 取消初始化要返回到空閑對(duì)象池的實(shí)例-即從池中歸還一個(gè)對(duì)象時(shí)調(diào)用
*
* @param pooledObject
* @throws Exception
*/
@Override
public void passivateObject(PooledObject<InfluxDBClient> pooledObject) throws Exception {
System.out.println("取消初始化要返回到空閑對(duì)象池的實(shí)例-即從池中歸還一個(gè)對(duì)象時(shí)調(diào)用");
}
/**
* 確保實(shí)例可以安全地由池返回澜倦。
*
* @param pooledObject
* @return 如果obj無效并且應(yīng)該從池中刪除聚蝶,則為false ,否則為true
*/
@Override
public boolean validateObject(PooledObject<InfluxDBClient> pooledObject) {
InfluxDBClient influxDBClient = pooledObject.getObject();
HealthCheck health = influxDBClient.health();
return HealthCheck.StatusEnum.PASS.equals(health.getStatus());
}
}
3藻治、創(chuàng)建對(duì)象池碘勉,繼承GenericObjectPool
import com.influxdb.client.InfluxDBClient;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.AbandonedConfig;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
/**
* @author Jenson
*/
public class InluxdbClientPool extends GenericObjectPool<InfluxDBClient> {
public InluxdbClientPool(PooledObjectFactory<InfluxDBClient> factory) {
super(factory);
}
public InluxdbClientPool(PooledObjectFactory<InfluxDBClient> factory, GenericObjectPoolConfig<InfluxDBClient> config) {
super(factory, config);
}
public InluxdbClientPool(PooledObjectFactory<InfluxDBClient> factory, GenericObjectPoolConfig<InfluxDBClient> config, AbandonedConfig abandonedConfig) {
super(factory, config, abandonedConfig);
}
}
4、創(chuàng)建對(duì)象池自動(dòng)裝配配置類桩卵,將對(duì)象池做成一個(gè)Bean
import com.influxdb.client.InfluxDBClient;
import com.jenson.factory.InfluxdbPooledObjectFactory;
import com.jenson.pool.InluxdbClientPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PreDestroy;
/**
* 對(duì)象池自動(dòng)裝配
*
* @author Jenson
*/
@Configuration
public class InfluxdbPoolAutoConfig {
private InluxdbClientPool pool;
@ConditionalOnClass({InfluxdbPooledObjectFactory.class})
@Bean("inluxdbClientPool")
protected InluxdbClientPool createInluxdbClientPool(){
InfluxdbPooledObjectFactory factory = new InfluxdbPooledObjectFactory();
// 設(shè)置對(duì)象池相關(guān)參數(shù)
GenericObjectPoolConfig<InfluxDBClient> poolConfig = new GenericObjectPoolConfig<>();
/**
* 最大空閑
*/
poolConfig.setMaxIdle(5);
/**
* 最大總數(shù)
*/
poolConfig.setMaxTotal(10);
/**
* 最小空閑
*/
poolConfig.setMinIdle(2);
poolConfig.setBlockWhenExhausted(true);
poolConfig.setTestOnBorrow(true);
poolConfig.setTestOnReturn(true);
poolConfig.setTestWhileIdle(true);
poolConfig.setTimeBetweenEvictionRunsMillis(1000 * 60 * 30);
//一定要關(guān)閉jmx验靡,不然springboot啟動(dòng)會(huì)報(bào)已經(jīng)注冊(cè)了某個(gè)jmx的錯(cuò)誤
poolConfig.setJmxEnabled(false);
// 新建一個(gè)對(duì)象池,傳入對(duì)象工廠和配置
pool = new InluxdbClientPool(factory, poolConfig);
initPool(3, 5);
return pool;
}
/**
* 預(yù)先加載testObject對(duì)象到對(duì)象池中
*
* @param initialSize 初始化連接數(shù)
* @param maxIdle 最大空閑連接數(shù)
*/
private void initPool(int initialSize, int maxIdle) {
if (initialSize <= 0) {
return;
}
int size = Math.min(initialSize, maxIdle);
for (int i = 0; i < size; i++) {
try {
pool.addObject();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
@PreDestroy
public void destroy() {
if (pool != null) {
pool.close();
}
}
}
5、使用池
從池中取出對(duì)象使用雏节,結(jié)束后再將對(duì)象歸還
@GetMapping("/get-influx-data")
public List<FluxRecord> getInfluxData(@RequestParam Integer startTime) {
String query = "from(bucket: \"zzs\") |> range(start: -"+startTime+"h) |> filter(fn: (r) => r._measurement == \"mem\")";
List<FluxTable> tables = new ArrayList<>();
// tables = influxdbClient.getQueryApi().query(query, "jenson");
InfluxDBClient poolClient = null;
try {
poolClient = inluxdbClientPool.borrowObject();
System.out.println("poolClient hashcode : "+poolClient.hashCode());
tables = poolClient.getQueryApi().query(query, "jenson");
} catch (Exception e) {
e.printStackTrace();
}
finally {
if (poolClient != null) {
//最終歸還對(duì)象到對(duì)象池
inluxdbClientPool.returnObject(poolClient);
}
}
List<FluxRecord> fluxRecords = new ArrayList<>();
tables.forEach(fluxTable -> {
List<FluxRecord> records = fluxTable.getRecords();
fluxRecords.addAll(records);
});
return fluxRecords;
}
如果注釋掉歸還對(duì)象的這一步胜嗓,可以看到每次調(diào)用接口控制它輸出對(duì)象的hashcode都是不同的,超過三次后就會(huì)新建對(duì)象钩乍,當(dāng)達(dá)到最大MaxTotal時(shí)辞州,程序會(huì)等待直到有對(duì)象歸還到池中,所以從池中取出對(duì)象使用完后務(wù)必要將對(duì)象歸還寥粹。