Skip to main content

2.Dubbo泛化调用

什么是泛化调用?

如果有使用过dubbo的都知道,一般我们都会有一个api层,提供一个RPC接口,供调用方去使用,但在网关服务中,网关是不可能去依赖提供方服务的api的,因此就有了泛化调用

调用方在没有服务方的API(SDK)时,仍然可以对服务方进行调用,就是泛化调用

泛化调用这部分,使用的是dubbo,参考实现

https://cn.dubbo.apache.org/zh-cn/overview/mannual/java-sdk/advanced-features-and-usage/service/generic-reference/

api-Gateway2版本中,可以看到SessionChannelInitializer 引入了一个Configuration

在该configuration构造器中,做了泛化调用调用方的初始化动作

  • 创建ApplicationConfig 应用配置类
  • 创建RegistryConfig 注册中心配置类
  • 创建ReferenceConfig 服务引用配置类

在引用配置类中添加ReferenceConfig.setGeneric(true)表示开启泛化调用

然后将上面所述的三个类都放在一个Map池里,用于后续使用

关于Configuration这部分,就已经改造完成了,主要是用来存放泛化调用相关的信息,再继续通过 SessionChannelInitializer来看SessionServerHandler 这个会话服务处理器

重点看如下两行

IGenericReference reference = configuration.getGenericReference("sayHi");
String result = reference.$invoke("test") + " " + System.currentTimeMillis();

getGenericReference获取的是GenericReferenceRegistry,泛化调用注册器

GenericReferenceRegistry 内部提供了两个方法

  1. getGenericReference 获取泛化调用接口
  2. addGenericReference 添加泛化调用接口

GenericReferenceRegistry#addGenericReference

首先,我们从配置的添加开始,通过 Configuration 类获取获取应用配置,注册配置,引用配置。

接下来,通过 DubboBootstrap 构建 Dubbo 服务。在构建的过程中,Dubbo内部会将泛化调用存放至 ReferenceConfigCache 中。

当我们通过 ReferenceConfigCache 获取到泛化服务 GenericService 后,会使用 GenericReferenceProxyFactory 泛化调用代理工厂对其进行包装。

之所以使用GenericReferenceProxyFactory进行包装的原因是可以直接通过该类,内部去处理代理相关逻辑,进行一个内聚

然后,将包装后的 GenericReferenceProxyFactory 存放到 knownGenericReferences 缓存池中。


GenericReferenceRegistry#getGenericReference

看完了添加,我们再来看是如何去获取泛化调用的,入参为String类型的methodName

通过方法名,去从knownGenericReferences里获取GenericReferenceProxyFactory,随即调用该类的newInstance,进行代理类的实例化创建

newInstance内部,首先是IGenericReference,他是统一泛化调用的接口,也就是所有代理类的接口

其次是GenericReferenceProxy 泛化调用代理类,最后代理类会走该类,通过这里能看出来enhancer.setCallback(genericReferenceProxy)

GenericReferenceProxy实现了MethodInterceptor

最后在GenericReferenceProxy#intercept我们可以看到,他走的是GenericService$invoke,也就是Dubbo的泛化调用

return genericService.$invoke(methodName, parameters, args);

MethodInterceptor 是 CGLIB 中的一个接口,用于拦截对目标对象方法的调用,并在调用前后执行自定义的逻辑,这也是为什么callback能设置genericReferenceProxy的原因,因为MethodInterceptor 内部继承了Callback

至此,泛化调用相关的内容已经迭代完毕,剩下的小部分是将启动流程做了一些变动和优化

增加了IGenericReferenceSessionFactory会话工厂类,用来启动api-gateway

调用openSession即可,为了隐藏细节,又增加了 GenericReferenceSessionFactoryBuilder启动构造器

使用该构造器,只需要调用build 传入一个Configuration,即可完成网关服务的启动