一,首先,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);

完成