400 028 6601

建站动态

根据您的个性需求进行定制 先人一步 抢占小程序红利时代

基于Apache-Commons-Pool2实现Grpc客户端连接池

概述

在项目运行过程中,有些操作对系统资源消耗较大,比如建立数据库连接、建立redis连接等操作,我们希望一次性创建多个连接对象,并在以后需要使用时能直接使用已创建好的连接,达到提高性能的目的。池技术通过提前将一些占用较多资源的对象初始化,并将初始化后的对象保存到池中备用,达到提高应用服务性能的目的,数据库的JDBC连接池和Jedis连接池等都使用了池技术。
Apache-Commons-Pool2提供了一套池技术的规范接口和实现的通用逻辑,我们只需要实现其抽象出来的方法就可以了。这篇博文主要分享基于Apache-Commons-Pool2来实现Grpc连接池的应用。
关于Grpc相关的内容,大家如想了解基本的实现方法,可以参考我的另一篇博客(传送门):https://blog.51cto.com/andrewli/2058908

成都创新互联专注于企业全网整合营销推广、网站重做改版、红河哈尼网站定制设计、自适应品牌网站建设、H5网站设计商城网站开发、集团公司官网建设、成都外贸网站建设公司、高端网站制作、响应式网页设计等建站业务,价格优惠性价比高,为红河哈尼等各大城市提供网站开发制作服务。

核心组件

我们先来了解一下Apache-Commons-Pool2规范接口中涉及到的几个核心组件,包括:

工作流程

根据上述对核心组件的类继承关系分析,我们可以梳理出一个流程,逐步实现各个组件,并组合成一套适用于我们业务的连接池架构。我们来看看这个流程该如何定义。
(1)定义我们的池内对象类 ClientObject,并结合我们的实际业务来实现上层接口的方法。
(2)定义对象工厂类ClientFactory,并结合我们的实际业务来实现上层接口的方法。
(3)定义池属性类ClientPoolConfig,结合我们的实际需求来设置属性值。
(4)使用对象池GenericObjectPool,指定泛型类型GenericObjectPool

基于Apache-Commons-Pool2实现Grpc客户端连接池

连接池内部的核心业务逻辑:
基于Apache-Commons-Pool2实现Grpc客户端连接池

池内对象的创建和返回逻辑是池技术里的关键,可以查看池对象的borrowObject方法去了解这部分细节内容。

应用实践

代码实现

根据上述对Apache-commons-pool2的特点和实现流程的分析,我们基于Grpc客户端连接池的应用场景,来进行代码实践,主要包括实现池内对象类 ClientObject和实现对象工厂类ClientFactory。
具体代码可以进入我的百度网盘下载,链接如下:
https://pan.baidu.com/s/1eaGpz6XN2a3ssw0eYsNLww

代码测试

为了验证我们的Grpc连接池的作用,我编写了一个测试方法,模拟以下场景,即开启10个线程,每个线程循环10次使用Grpc连接发送消息给grpc服务端,然后查看线程池中累计创建的连接对象个数、线程池中每个连接对象的被使用次数等信息。
通过测试输出的信息,我得到的结论是:不使用连接池时,总共需要进行100次Grpc连接并发送消息;使用连接池后,总共仅需要建立2次Grpc连接来发送100次消息,每个连接被调用了50次。
测试代码如下。

package com.cmcc.littlec.grpc.poolclient;
import com.cmcc.littlec.grpc.util.Constants;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

public class test {
    @SuppressWarnings("unchecked")
    public static GenericObjectPool getClientPool(){
        ClientPoolFactory factory = new ClientPoolFactory(Constants.grpcHost, Constants.grpcPort);
        GenericObjectPoolConfig config = new GenericObjectPoolConfig();
        config.setMaxIdle(8);
        config.setMinIdle(3);
        config.setMaxTotal(18);
        config.setTestOnBorrow(true);
        config.setTestOnReturn(true);
        GenericObjectPool clientPool = new GenericObjectPool(factory, config);
        return clientPool;
    }

    public static void  main(String[] args ){
        final GenericObjectPool clientPool = getClientPool();
        for(int i=0; i<10; i++) {
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        for (int i = 0; i < 10; i++) {
                            ClientObject client = clientPool.borrowObject();                                                        
                            String str = "hello, grpc client_" + i;//参数
                            try {
                                client.sayHello(str);
                            }catch(Exception e){
                                client.invalidate();
                            }
                            System.out.println("Thread : " + Thread.currentThread().getName() + "; clientPool size : " + clientPool.getCreatedCount());
                            System.out.println("clientObj : "+client.toString());
                            clientPool.returnObject(client);
                        }
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                }
            });
            t.start();
            try {
                if(i%2==0) {
                    Thread.sleep(5000L);//每隔两个线程创建后停顿5S
                }
            }catch(Exception e){ }
        }
    }
}

新闻标题:基于Apache-Commons-Pool2实现Grpc客户端连接池
文章URL:http://www.bluegullmedia.com/article/iecspd.html

其他资讯

让你的专属顾问为你服务

0.3480s