4.数据源抽离
在网关中,对于请求方式,如(RPC、HTTP)都可以抽象的理解成为一种数据源,就单单拿出 RPC来说,还有各厂的RPC。到底使用哪一套呢?因此我们在设计上,应该把它抽离出来,这样后续在扩展,包括使用上,都会方便很多
本章节新增datasource目录,也就是数据源的实现
不同数据源有不同的实现,如何约束开发者,我们需要提供一个标准接口,分别是
Connection
(连接器) 和Datasouce
(数据源)
从代码层面上,理解一下数据源到底做了那些事
首先还是从数据源的入口处开始看,也就是会话工厂 DefaultGatewaySessionFactory
会话工厂管理开启和关闭会话,一个网关项目,肯定会存在多个会话。通过开启会话,然后获取数据源,而 数据源又包含了连接(Connection)
public interface DataSource {
//内部getConnection,应当负责执行器服务的创建
Connection getConnection();
}
让我们从数据源的实现开始说起,来反推接口内部的职责到底应该是什么
数据源分为从大的概念上来讲,可以分为池化数据源和无池化数据源,我们继续细分。还可以有不同类型的数据源,在本章节中 只进行了池化和无池化的区分,当然池化数据源的设计并没有实现,只有一个无池化的视线,我们就看这个就足够了
有两个类UnpooledDataSourceFactory
和 UnpooledDataSource
工厂设计模式,在小傅哥的网关真的是随处可见,工厂就是用来管理具体的实现创建,而不需要真正关心实现,只需要通过工厂,进行创建即可。不理解的小伙伴把它当成前台服务人员就行,你不需要关心内部流程如何去做,你只需要和前台服务人员打好关系即可,这样做可以减少耦合,从使用的角度来讲,也轻松了很多
然后就是UnpooledDataSource
public class UnpooledDataSource implements DataSource {
private Configuration configuration;
private HttpStatement httpStatement;
private DataSourceType dataSourceType;
@Override
public Connection getConnection() {
switch (dataSourceType) {
case HTTP:
// TODO 预留接口,暂时不需要实现
break;
case Dubbo:
// 配置信息
String application = httpStatement.getApplication();
String interfaceName = httpStatement.getInterfaceName();
// 获取服务
ApplicationConfig applicationConfig = configuration.getApplicationConfig(application);
RegistryConfig registryConfig = configuration.getRegistryConfig(application);
ReferenceConfig<GenericService> reference = configuration.getReferenceConfig(interfaceName);
return new DubboConnection(applicationConfig, registryConfig, reference);
default:
break;
}
throw new RuntimeException("DataSourceType:" + dataSourceType + "没有对应的数据源实现");
}
}
主要看Dubbo相关,开始 流程还是与之前保持一致,通过configuration获取应用服务,注册服务,引用服务。但最后引入了一个DubboConnection
因为我们的接口,要求返回一个Connection类型,所以dubbo的实现也应该返回一个自定义的DubboConnection
public class DubboConnection implements Connection {
private final GenericService genericService;
public DubboConnection(ApplicationConfig applicationConfig, RegistryConfig registryConfig, ReferenceConfig<GenericService> reference) {
// 连接远程服务
DubboBootstrap bootstrap = DubboBootstrap.getInstance();
bootstrap.application(applicationConfig).registry(registryConfig).reference(reference).start();
// 获取泛化接口
ReferenceConfigCache cache = ReferenceConfigCache.getCache();
genericService = cache.get(reference);
}
/**
* Dubbo 泛化调用:https://dubbo.apache.org/zh/docsv2.7/user/examples/generic-reference/
*/
@Override
public Object execute(String method, String[] parameterTypes, String[] parameterNames, Object[] args) {
return genericService.$invoke(method, parameterTypes, args);
}
}
可以看到,在创建DubboConecction
的时候,会进行泛化调用的构建,需要使用时,可以直接通过execute
进行调用。HTTPConnection
也是同样的逻辑
最后有一个小细节,在无池化数据源工厂UnpooledDataSourceFactory
public class UnpooledDataSourceFactory implements DataSourceFactory {
protected UnpooledDataSource dataSource;
public UnpooledDataSourceFactory() {
this.dataSource = new UnpooledDataSource();
}
@Override
public void setProperties(Configuration configuration, String uri) {
this.dataSource.setConfiguration(configuration);
this.dataSource.setDataSourceType(DataSourceType.Dubbo);
this.dataSource.setHttpStatement(configuration.getHttpStatement(uri));
}
}
setProperties的命名就很好,Properties
表示所有的配置项,里面有Configuration
,DataSouceType
,以及HttpStatement
。到此本章就结束了,在理解connection内部是如何开发之后,我们其实也能按照对应的上层接口去实现一套自己的数据源
这套实现和ORM的实现基本类似,参考mybatis