dubbo架构
RPC调用链如下
更多架构请参考dubbo官方开发者指南http://dubbo.apache.org/en-us/docs/dev/design.html
通过这个流程图可以看到dubbo的调用链是非常复杂的,并且dubbo抽象了非常多的SPI接口,保证了dubbo的扩展性。让dubbo是一个非常容易扩展的框架。
- ProxyFactory SPI接口实现Invoker和服务接口和对象的相互转换
- Filter SPI接口实现Invoker调用链的拦截,自由的添加扩展逻辑
- Invoker接口实现可以实现本地以及远程service方法的调用
- Cluster SPI接口可以实现从Invoker
- Directory选择Invoker来实现失败重试策略
- LoadBalance SPI接口可以实现从多个可用的Invoker中负载均衡策略
- Registry SPI接口可以实现URL的注册,查找和订阅,取消订阅
- Protocol SPI接口实现基于service调用的入参,调用对应网络通讯框架来创建远程方法调用Invoker。
- Directory接口实现RegistryDirectory通过Registry订阅到服务提供方的List,根据每个提供方URL调用Protocol实现类创建Invoker, 实现根据远程方法调用信息Invocation信息返回Invoker List
dubbo核心接口之 Invoker对象
dubbo里面大部分方法的入参都是Invoker对象,是dubbo里面最核心的接口
package com.alibaba.dubbo.rpc;
import com.alibaba.dubbo.common.Node;
/**
* Invoker. (API/SPI, Prototype, ThreadSafe)
*
* @see com.alibaba.dubbo.rpc.Protocol#refer(Class, com.alibaba.dubbo.common.URL)
* @see com.alibaba.dubbo.rpc.InvokerListener
* @see com.alibaba.dubbo.rpc.protocol.AbstractInvoker
* @author william.liangf
*/
public interface Invoker<T> extends Node {
/**
* get service interface.
*
* @return service interface.
*/
Class<T> getInterface();
/**
* invoke.
*
* @param invocation
* @return result
* @throws RpcException
*/
Result invoke(Invocation invocation) throws RpcException;
}
import com.alibaba.dubbo.common.URL;
/**
* Node. (API/SPI, Prototype, ThreadSafe)
*
* @author william.liangf
*/
public interface Node {
/**
* get url.
*
* @return url.
*/
URL getUrl();
/**
* is available.
*
* @return available.
*/
boolean isAvailable();
/**
* destroy.
*/
void destroy();
}
dubbo的数据总线URL对象描述了请求的协议类型,请求参数数据,dubbo.xml里面的配置参数信息都会转化为url对象用于整个调用链来传递配置信息。
dubbo客户端注册到注册中心的url实例 consumer://192.168.0.1/com.dq.test.xxxService?application=sita-crm-front&category=consumers&check=false&default.check=false&dubbo=2.8.4&group=crm-web&interface=com.dq.test.xxxService&pid=733&revision=0.0.1-SNAPSHOT&side=consumer&timeout=60000×tamp=1537006745855
dubbo服务端注册到注册中心的url实例 dubbo://192.168.0.1:20880/xxxService?anyhost=true&application=crm-web&default.delay=-1&default.group=crm-web&default.timeout=10000&delay=-1&dubbo=2.8.4&generic=false&interface=xxxService&pid=610&revision=0.0.1-SNAPSHOT&side=provider×tamp=1537005166465
Invocation对象的实现封装了远程调用的请求数据,默认的实现是RpcInvocation类
public interface Invocation {
/**
* get method name.
*
* @serial
* @return method name.
*/
String getMethodName();
/**
* get parameter types.
*
* @serial
* @return parameter types.
*/
Class<?>[] getParameterTypes();
/**
* get arguments.
*
* @serial
* @return arguments.
*/
Object[] getArguments();
/**
* get attachments.
*
* @serial
* @return attachments.
*/
Map<String, String> getAttachments();
/**
* get attachment by key.
*
* @serial
* @return attachment value.
*/
String getAttachment(String key);
/**
* get attachment by key with default value.
*
* @serial
* @return attachment value.
*/
String getAttachment(String key, String defaultValue);
/**
* get the invoker in current context.
*
* @transient
* @return invoker.
*/
Invoker<?> getInvoker();
}
dubbo核心之Protocal
@SPI("dubbo")
public interface Protocol {
/**
* 获取缺省端口,当用户没有配置端口时使用。
*
* @return 缺省端口
*/
int getDefaultPort();
/**
* 暴露远程服务:<br>
* 1. 协议在接收请求时,应记录请求来源方地址信息:RpcContext.getContext().setRemoteAddress();<br>
* 2. export()必须是幂等的,也就是暴露同一个URL的Invoker两次,和暴露一次没有区别。<br>
* 3. export()传入的Invoker由框架实现并传入,协议不需要关心。<br>
*
* @param <T> 服务的类型
* @param invoker 服务的执行体
* @return exporter 暴露服务的引用,用于取消暴露
* @throws RpcException 当暴露服务出错时抛出,比如端口已占用
*/
@Adaptive
<T> Exporter<T> export(Invoker<T> invoker) throws RpcException;
/**
* 引用远程服务:<br>
* 1. 当用户调用refer()所返回的Invoker对象的invoke()方法时,协议需相应执行同URL远端export()传入的Invoker对象的invoke()方法。<br>
* 2. refer()返回的Invoker由协议实现,协议通常需要在此Invoker中发送远程请求。<br>
* 3. 当url中有设置check=false时,连接失败不能抛出异常,并内部自动恢复。<br>
*
* @param <T> 服务的类型
* @param type 服务的类型
* @param url 远程服务的URL地址
* @return invoker 服务的本地代理
* @throws RpcException 当连接服务提供方失败时抛出
*/
@Adaptive
<T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;
/**
* 释放协议:<br>
* 1. 取消该协议所有已经暴露和引用的服务。<br>
* 2. 释放协议所占用的所有资源,比如连接和端口。<br>
* 3. 协议在释放后,依然能暴露和引用新的服务。<br>
*/
void destroy();
}