大橙子网站建设,新征程启航
为企业提供网站建设、域名注册、服务器等服务
在项目运行过程中,有些操作对系统资源消耗较大,比如建立数据库连接、建立redis连接等操作,我们希望一次性创建多个连接对象,并在以后需要使用时能直接使用已创建好的连接,达到提高性能的目的。池技术通过提前将一些占用较多资源的对象初始化,并将初始化后的对象保存到池中备用,达到提高应用服务性能的目的,数据库的JDBC连接池和Jedis连接池等都使用了池技术。
Apache-Commons-Pool2提供了一套池技术的规范接口和实现的通用逻辑,我们只需要实现其抽象出来的方法就可以了。这篇博文主要分享基于Apache-Commons-Pool2来实现Grpc连接池的应用。
关于Grpc相关的内容,大家如想了解基本的实现方法,可以参考我的另一篇博客(传送门):https://blog.51cto.com/andrewli/2058908
成都创新互联专注于企业全网整合营销推广、网站重做改版、红河哈尼网站定制设计、自适应品牌网站建设、H5网站设计、商城网站开发、集团公司官网建设、成都外贸网站建设公司、高端网站制作、响应式网页设计等建站业务,价格优惠性价比高,为红河哈尼等各大城市提供网站开发制作服务。
我们先来了解一下Apache-Commons-Pool2规范接口中涉及到的几个核心组件,包括:
在梳理连接池相关的核心组件工作流程之前,我们先来了解一下核心组件涉及到的类和接口之间的继承和实现关系。
对象池类的继承关系
对象池的最顶层接口是ObjectPool
抽象类BaseGenericObjectPool
池类GenericObjectPool
由于GenericObjectPool
池属性类的继承关系
池属性的最上层接口是interface Cloneable,抽象类BaseObjectPoolConfig实现了这个接口,并定义了默认的池配置属性。
GenericObjectPoolConfig类继承了BaseObjectPoolConfig,同样定义了默认的池配置属性值。
我们可以直接使用GenericObjectPoolConfig类,或者继承GenericObjectPoolConfig类,根据自己的需求设置自定义池配置属性。
池内对象类的继承关系
池内对象类实现了上层的PooledObject
另外,池内对象类还需要定义类本身需要具备的成员属性和需要实现的业务方法。
根据上述对核心组件的类继承关系分析,我们可以梳理出一个流程,逐步实现各个组件,并组合成一套适用于我们业务的连接池架构。我们来看看这个流程该如何定义。
(1)定义我们的池内对象类 ClientObject,并结合我们的实际业务来实现上层接口的方法。
(2)定义对象工厂类ClientFactory,并结合我们的实际业务来实现上层接口的方法。
(3)定义池属性类ClientPoolConfig,结合我们的实际需求来设置属性值。
(4)使用对象池GenericObjectPool,指定泛型类型GenericObjectPool
连接池内部的核心业务逻辑:
池内对象的创建和返回逻辑是池技术里的关键,可以查看池对象的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){ }
}
}
}