一,首先,grpc有没有必要实现连接池?
测试及分析见前文:记一次web请求量上不去的排查记录,及grpc client请求优化
二,如果我们确实需要实现自己的连接池,代码如下:
1.首先引入apache的池化包
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.5.0</version>
</dependency>
2.实现自己的连接池
import cn.sdwan.major.service.impl.HomePageServiceImpl;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ChannelStatePool {
private static final Logger log = LoggerFactory.getLogger(ChannelStatePool.class);
private static GenericObjectPool<ChannelStateClient> objectPool=null;
static {
// 连接池的配置
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
// 池中的最大连接数
poolConfig.setMaxTotal(5);
// 最少的空闲连接数
poolConfig.setMinIdle(1);
// 最多的空闲连接数
poolConfig.setMaxIdle(4);
// 当连接池资源耗尽时,调用者最大阻塞的时间,超时时抛出异常 单位:毫秒数
poolConfig.setMaxWaitMillis(5000);
// 连接池存放池化对象方式,true放在空闲队列最前面,false放在空闲队列最后
poolConfig.setLifo(true);
// 连接空闲的最小时间,达到此值后空闲连接可能会被移除,默认即为30分钟
poolConfig.setMinEvictableIdleTimeMillis(1000L * 60L * 30L);
// 连接耗尽时是否阻塞,默认为true
poolConfig.setBlockWhenExhausted(true);
// 连接池创建
objectPool = new GenericObjectPool<>(new ChannelStateFactory(), poolConfig);
}
/**
* 从连接池获取对象
*/
public static ChannelStateClient borrowObject(){
log.debug("borrowObject");
try {
ChannelStateClient clientSingle = objectPool.borrowObject();
log.debug("总创建线程数,{}",objectPool.getCreatedCount());
return clientSingle;
} catch (Exception e) {
e.printStackTrace();
}
//连接池失败则主动创建
return createClient();
}
/**
* 还回连接池获取的对象
*/
public static void returnObject(ChannelStateClient channelStateClient){
log.debug("returnObject");
try {
objectPool.returnObject(channelStateClient);
log.debug("总创建线程数,{}",objectPool.getCreatedCount());
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 当连接池异常,则主动创建对象
*/
private static ChannelStateClient createClient(){
return new ChannelStateClient("channel", 8080);
}
/**
* 执行器
* @param workCallBack 主要服务内容
*/
public static Runnable execute(WorkCallBack<ChannelStateClient> workCallBack){
return () -> {
ChannelStateClient client = borrowObject();
try {
workCallBack.callback(client);
} finally {
/** 将连接对象返回给连接池 */
objectPool.returnObject(client);
}
};
}
}
3.创建一个需要池化对象的工厂类
import cn.sdwan.major.service.impl.HomePageServiceImpl;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ChannelStatePool {
private static final Logger log = LoggerFactory.getLogger(ChannelStatePool.class);
private static GenericObjectPool<ChannelStateClient> objectPool=null;
static {
// 连接池的配置
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
// 池中的最大连接数
poolConfig.setMaxTotal(5);
// 最少的空闲连接数
poolConfig.setMinIdle(1);
// 最多的空闲连接数
poolConfig.setMaxIdle(4);
// 当连接池资源耗尽时,调用者最大阻塞的时间,超时时抛出异常 单位:毫秒数
poolConfig.setMaxWaitMillis(5000);
// 连接池存放池化对象方式,true放在空闲队列最前面,false放在空闲队列最后
poolConfig.setLifo(true);
// 连接空闲的最小时间,达到此值后空闲连接可能会被移除,默认即为30分钟
poolConfig.setMinEvictableIdleTimeMillis(1000L * 60L * 30L);
// 连接耗尽时是否阻塞,默认为true
poolConfig.setBlockWhenExhausted(true);
// 连接池创建
objectPool = new GenericObjectPool<>(new ChannelStateFactory(), poolConfig);
}
/**
* 从连接池获取对象
*/
public static ChannelStateClient borrowObject(){
log.debug("borrowObject");
try {
ChannelStateClient clientSingle = objectPool.borrowObject();
log.debug("总创建线程数,{}",objectPool.getCreatedCount());
return clientSingle;
} catch (Exception e) {
e.printStackTrace();
}
//连接池失败则主动创建
return createClient();
}
/**
* 还回连接池获取的对象
*/
public static void returnObject(ChannelStateClient channelStateClient){
log.debug("returnObject");
try {
objectPool.returnObject(channelStateClient);
log.debug("总创建线程数,{}",objectPool.getCreatedCount());
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 当连接池异常,则主动创建对象
*/
private static ChannelStateClient createClient(){
return new ChannelStateClient("channel", 8080);
}
4.使用该连接池,并还回该对象
//借用
ChannelStateClient client=ChannelStatePool.borrowObject();
//使用
Obeject res = client.getObj();
//归还
ChannelStatePool.returnObject(client);
完成