apache common pool2对象池应用之elasticsearch TransportClient

发布于 2019-09-26 作者 风铃 180次 浏览 版块 前端

maven项目引入依赖:

<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 -->

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.4.2</version>
</dependency>

基本介绍:

在此例中,对象池中存储的是elasticsearch TransportClient,是个大对象(生成比较耗时)。我们使用common pool池化技术,预加载client对象,使用的时候只需要从池中拿即可。

基本api调用方式如下:

 GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();//对象池配置类,不写也可以,采用默认配置
poolConfig.setMaxTotal(list.length);//采用默认配置maxTotal是8,池中有8个client
EsClientPoolFactory esClientPoolFactory = new EsClientPoolFactory();//要池化的对象的工厂类,这个是我们要实现的类
GenericObjectPool<TransportClient> clientPool = new GenericObjectPool<>(esClientPoolFactory,poolConfig);//利用对象工厂类和配置类生成对象池
client = clientPool.borrowObject(); //从池中取一个对象
clientPool.returnObject(client);//使用完毕之后,归还对象

下面是工厂类代码:

import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.transport.client.PreBuiltTransportClient;

import java.net.InetAddress;
import java.net.UnknownHostException;

public class EsClientPoolFactory implements PooledObjectFactory<TransportClient> {

@Override

    //生成pooledObject
public PooledObject<TransportClient> makeObject() throws Exception {
Settings settings = Settings.builder().put("cluster.name","elasticsearch").build();
TransportClient client = null;
try {
client = new PreBuiltTransportClient(settings)
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"),9300));
} catch (UnknownHostException e) {
e.printStackTrace();
}
return new DefaultPooledObject<TransportClient>(client);
}

@Override

    //销毁对象
public void destroyObject(PooledObject<TransportClient> pooledObject) throws Exception {
TransportClient client = pooledObject.getObject();
client.close();
}

@Override

    //验证对象
public boolean validateObject(PooledObject<TransportClient> pooledObject) {
return true;
}

@Override

    //激活对象
public void activateObject(PooledObject<TransportClient> pooledObject) throws Exception {
System.out.println("activate esClient");
}

@Override

    //钝化对象
public void passivateObject(PooledObject<TransportClient> pooledObject) throws Exception {
System.out.println("passivate Object");
}
}

①:当在GenericObjectPool类中调用borrowObject方法时,如果当前对象池中没有空闲的对象,GenericObjectPool会调用这个方法,创建一个对象,并把这个对象封装到PooledObject类中,并交给对象池管理。

②:void destroyObject(PooledObject<T> p) throws Exception;

销毁对象,当对象池检测到某个对象的空闲时间(idle)超时,或使用完对象归还到对象池之前被检测到对象已经无效时,就会调用这个方法销毁对象。对象的销毁一般和业务相关,但必须明确的是,当调用这个方法之后,对象的生命周期必须结果。如果是对象是线程,线程必须已结束,如果是socketsocket必须已close,如果是文件操作,文件数据必须已flush,且文件正常关闭。
③:boolean validateObject(PooledObject<T> p);

检测一个对象是否有效。在对象池中的对象必须是有效的,这个有效的概念是,从对象池中拿出的对象是可用的。比如,如果是socket,那么必须保证socket是连接可用的。在从对象池获取对象或归还对象到对象池时,会调用这个方法,判断对象是否有效,如果无效就会销毁。
④:void activateObject(PooledObject<T> p) throws Exception;

激活一个对象或者说启动对象的某些操作。比如,如果对象是socket,如果socket没有连接,或意外断开了,可以在这里启动socket的连接。它会在检测空闲对象的时候,如果设置了测试空闲对象是否可以用,就会调用这个方法,在borrowObject的时候也会调用。另外,如果对象是一个包含参数的对象,可以在这里进行初始化。让使用者感觉这是一个新创建的对象一样。
⑤:void passivateObject(PooledObject<T> p) throws Exception;

钝化一个对象。在向对象池归还一个对象是会调用这个方法。这里可以对对象做一些清理操作。比如清理掉过期的数据,下次获得对象时,不受旧数据的影响。

一般来说activateObjectpassivateObject是成对出现的。前者是在对象从对象池取出时做一些操作,后者是在对象归还到对象池做一些操作,可以根据自己的业务需要进行取舍。

收藏
暂无回复