从Java 1.5开始,JDK就提供了Callable和Future,通过它们可以在任务异步执行完毕之后获取任务的执行结果。
Netty扩展了JDK中的Future机制,下面我们来看一张Netty中Future和Promise类关系图:
从Java 1.5开始,JDK就提供了Callable和Future,通过它们可以在任务异步执行完毕之后获取任务的执行结果。
Netty扩展了JDK中的Future机制,下面我们来看一张Netty中Future和Promise类关系图:
从Dubbo 2.7.0的项目依赖来看,依赖的Spring Framework版本是4.3.16.RELEASE
:
1 | <properties> |
Dubbo是基于Spring构建和运行的,兼容Spring配置,Dubbo利用了SpringFramework的Extensible XML authoring 特性,扩展了Spring标签,关于如何利用Spring扩展标签,可以参考官方文档 《Extensible XML authoring》:
编写xml,描述需要扩展的标签的配置属性,dubbo实现放在jar包META-INF/dubbo.xsd
文件里 同时通过编写META-INF/spring.handlers
文件,提供给spring,内容如下:
1 | http\://dubbo.apache.org/schema/dubbo=org.apache.dubbo.config.spring.schema.DubboNamespaceHandler |
编写一个NamespaceHandler接口实现类,dubbo中的实现类是DubboNamespaceHandler,同时通过编写META-INF/spring.schemas
文件提供给Spring,内容如下:
1 | http\://dubbo.apache.org/schema/dubbo/dubbo.xsd=META-INF/dubbo.xsd |
编写一个或多个BeanDefinitionParser实现类,用来解析扩展的元素,Dubbo实现类是DubboBeanDefinitionParaser
把以上解析组件注册给Spring
Dubbo是微内核架构,还是开闭原则的应用,把核心流程架构固定,但是流程的各个节点对重新改进是开放的。具体的实现机制就是SPI(Service Provider Interface)机制,Dubbo基于Java SPI机制(不了解Java SPI机制的可以参考这篇文章《深入理解Java SPI机制》),在其基础上做了改进和扩展。
根据SPI规范,接口由框架定义,具体实现可以由不同的厂商提供,在Dubbo jar包可以发现在/META-INF/dubbo/internal
目录下有许多接口命名的文件,文件里面的内容就是文件名代表的接口的各种实现类,这就是Dubbo SPI机制的配置基础,以org.apache.dubbo.rpc.Protocol
文件为例,内容如下(dubbo-2.7.0-SNAPSHOT 版本):
1 | filter=org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper |
在分析Dubbo RPC服务调用过程之前,我们先写一个基于Dubbo实现的Consumer-Provider的Demo,通过这个Demo来分析具体的RPC调用栈。
先定义一个接口:
1 | /** |
我们基于zookeeper注册中心,服务端配置如下:
1 | <dubbo:application name="dubbo-server" owner="Junlan" /> |
客户端配置如下:
1 | <dubbo:application name="dubbo-client" owner="Junlan"/> |
SPI的全名为Service Provider Interface,在java.util.ServiceLoader的文档:https://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html中有比较详细的介绍。究其思想,其实和Callback
差不多。Callback
的思想是我们在调用API的时候,我们可以写入一段逻辑代码传到API里面,API内部在合适的时候会调用它,从而实现某种程度上的“定制”。
典型的是Collections.sort(List<T> list,Comparator<? super T> c)
这个方法,它的第二个参数是一个实现Comparator接口的实例。我们可以根据自己的排序规则写一个类,实现此接口,传入此方法,那么这个方法就会根据我们的规则对list进行排序。
当服务的提供者,提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里同时创建一个以服务接口命名的文件。该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。
基于这样一个约定就能很好的找到服务接口的实现类,而不需要再代码里制定。
JDK提供服务实现查找的一个工具类:java.util.ServiceLoader
Update your browser to view this website correctly. Update my browser now