dubbo学习(三)实现细节

部分图片和描述来自官方文档,非原创

初始化过程细节

解析服务

解析服务是暴露服务(提供方 provider )和消费方(引用提供方的 service )的前一个步骤。

回想我们如何使用dubbo的

提供方

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	...
	<dubbo:provider protocol="dubbo" port="-1"/>
	<dubbo:service interface="com.general.msg.service.PushCommentMeMsgService" ref="pushCommentMeMsgService" version="2.0.0" retries="0" timeout="6000"/>
	<dubbo:service interface="com.general.msg.service.MessageDetailService" ref="messageDetailService" version="1.0.0" retries="0" />
	...

	</beans>

x消费方

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  	...
    <dubbo:consumer	check="false"/>
    <dubbo:reference interface="com.general.business.service.IndexDataService" id="indexDataService" version="1.0.0"/>
    <dubbo:reference interface="com.general.business.service.AppCommentService" id="appCommentService" version="2.0.0"/>
    ...


</beans>

下面我们看一下Dubbo 如何对XML的服务进行解析。

解析实现

基于 dubbo.jar 内的 META-INF/spring.handlers 配置,Spring 在遇到 dubbo 名称空间时,会回调 DubboNamespaceHandler。所有 dubbo 的标签,都统一用 DubboBeanDefinitionParser 进行解析,基于一对一属性映射,将 XML 标签解析为 Bean 对象。 我们看一下spring.handlers 是什么

http\://dubbo.apache.org/schema/dubbo=org.apache.dubbo.config.spring.schema.DubboNamespaceHandler
http\://code.alibabatech.com/schema/dubbo=org.apache.dubbo.config.spring.schema.DubboNamespaceHandler

可以知道这是利用SPI机制加载这两个类,然后对XML 进行解析。

在 ServiceConfig.export() 或 ReferenceConfig.get() 初始化时,将 Bean 对象转换 URL 格式,所有 Bean 属性转成 URL 的参数。

这两个方法非常重要!!ServiceConfig.export()是暴露服务用的;ReferenceConfig.get()

然后将 URL 传给 协议扩展点,基于扩展点的 扩展点自适应机制,根据 URL 的协议头,进行不同协议的服务暴露或引用。

暴露服务

1297993-20200303155308392-542944953.png

大致的过程如上,我们来看一下官方的描述,向注册中心暴露服务:

在有注册中心,需要注册提供者地址的情况下 [2],ServiceConfig 解析出的 URL 的格式为: registry://registry-host/org.apache.dubbo.registry.RegistryService?export=URL.encode("dubbo://service-host/com.foo.FooService?version=1.0.0"),基于扩展点自适应机制,通过 URL 的 registry:// 协议头识别,就会调用 RegistryProtocol 的 export() 方法,将 export 参数中的提供者 URL,先注册到注册中心。再重新传给 Protocol 扩展点进行暴露: dubbo://service-host/com.foo.FooService?version=1.0.0,然后基于扩展点自适应机制,通过提供者 URL 的 dubbo:// 协议头识别,就会调用 DubboProtocol 的 export() 方法,打开服务端口。 整个时序图如下 : 1297993-20200303155800141-1023474408.jpg 对应的export 方法在图中已经标出,方框这是注册到注册中心去的过程。

引用提供者服务

引用和暴露过程差不多,见官方文档 。

远程调用细节

上一节将的是初始化的过程,这一节将会讲如何调用和消费的问题。

概述

假如存在

//消费方 
public class DemoClientAction {
 
    private DemoService demoService;
 
    public void setDemoService(DemoService demoService) {
        this.demoService = demoService;
    }
 
    public void start() {
        String hello = demoService.sayHello("world" + i);
    }
}

上面代码中的 DemoService 就是上图中服务消费端的 proxy,用户代码通过这个 proxy 调用其对应的 Invoker [5],而该 Invoker 实现了真正的远程服务调用。

//提供方代码
public class DemoServiceImpl implements DemoService {
 
    public String sayHello(String name) throws RemoteException {
        return "Hello " + name;
    }
}


上面这个类会被封装成为一个 AbstractProxyInvoker 实例,并新生成一个 Exporter 实例。这样当网络通讯层收到一个请求后,会找到对应的 Exporter 实例,并调用它所对应的 AbstractProxyInvoker 实例,从而真正调用了服务提供者的代码。Dubbo 里还有一些其他的 Invoker 类,但上面两种是最重要的。

那么大概是如下的过程 : 1297993-20200303160936701-1017740085.jpg

可以知道 invoker 起到了一个承上启下的作用,在提供方和消费方之前形成了一个桥梁。

服务提供者暴露一个服务的详细过程

1297993-20200303160249291-1586092265.jpg

暴露过程也不能理解,主线就是 invoker ---> exporter对象的过程。

服务消费者消费一个服务的详细过程

1297993-20200303160158190-2024843830.jpg

线程派发模型

1297993-20200303161400814-362995203.jpg

参考资料

  • http://dubbo.apache.org/zh-cn/docs/dev/implementation.html

猜你喜欢

转载自www.cnblogs.com/Benjious/p/12402936.html