七Dubbo各模块的层次核心接口及组件类--3Protocol-RPC模块
七Dubbo各模块的层次核心接口及组件类--3Protocol-RPC模块
7.3 Protocol(RPC模块)
远程调用层:封装rpc调用,以invocation和result为中心,扩展接口为protocol、invoker和exporter。
模块 | Dubbo层 | 各层核心接口 |
---|---|---|
Service | ServiceBean ReferanceBean | |
dubbo-config | Config | ServiceConfig ReferanceConfig |
dubbo-RPC | Proxy | ServiceProxy ProxyFactory |
dubbo-registry | Registry | RegistryFactory Registry RegistryService |
dubbo-cluster | Cluster | Cluster Directory Router LoadBalance |
dubbo-monitor | Monitor | |
dubbo-RPC | Protocol | Filter Invoker Prococol Exporter |
: | Transport | Transport Channel Client Server Codec |
dubbo-remoting | Exchange | Exchanger ExchangeChannel ExchangeClient ExchangeServer |
dubbo-common | Serialize |
在protocol(远程调用层)层,发起服务暴露(protocol.export)和服务引用(protocol.refer)。
7.3.1 Filter
@SPI
public interface Filter {
/**
* filter的链式调用,本质是个around式的aop--即在拦截器链(filter会转化为invoker,链条上最后一个invoker为服务的实际invoker)的下一个invoker.invoke执行前后,分别执行相应的filter逻辑的操作。
* <code>
* // before filter
* Result result = invoker.invoke(invocation);
* // after filter
* return result;
* </code>
*
* @see com.alibaba.dubbo.rpc.Invoker#invoke(Invocation)
* @param invoker 为拦截器链上的下一个invoker
* @param invocation invocation.
* @return invoke result.
* @throws RpcException
*/
Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException;
}
filter中的invoke,实现链式调用。其本质是对invoker.invoke进行around的环绕增强。
7.3.1.1 filter关键内容
1 链式拦截原理
ProtocolFilterWrapper
//服务暴露过程,会构造invoker的拦截器链(获取所有激活的filter,创建invoker匿名类,在invoker.invoke中构造链式关系)
public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
return protocol.export(invoker);
}
return protocol.export(buildInvokerChain(invoker, Constants.SERVICE_FILTER_KEY, Constants.PROVIDER));
}
//服务引用过程,也会构造invoker的拦截器链
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
return protocol.refer(type, url);
}
return buildInvokerChain(protocol.refer(type, url), Constants.REFERENCE_FILTER_KEY, Constants.CONSUMER);
}
private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) {
Invoker<T> last = invoker;
//获取已经自动激活的filter对象
List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group);
if (filters.size() > 0) {
//倒序遍历filter,最后一个filter所构造的invoker,执行invoke时,是filter.invoke(next,invocation)。
for (int i = filters.size() - 1; i >= 0; i --) {
final Filter filter = filters.get(i);
final Invoker<T> next = last;
//将filter构造为invoker
last = new Invoker<T>() {
/** ……………………………………………将filter构造为invoker拦截器链,其方法,获取都是当前abstractProxyInvoker匿名类的属性…………………………………………*/
public Class<T> getInterface() {
return invoker.getInterface();
}
public URL getUrl() {
return invoker.getUrl();
}
public boolean isAvailable() {
return invoker.isAvailable();
}
public void destroy() {
invoker.destroy();
}
@Override
public String toString() {
return invoker.toString();
}
/**………………………………………………………………………………………………………………………链式调用的实现………………………………………………………………………………………………………………………… */
public Result invoke(Invocation invocation) throws RpcException {
return filter.invoke(next, invocation);
}
};
}
}
return last;
}
2 Filter的@Active自动激活原理--todo
7.3.2 Invoker
7.3.2.1 Invoker的接口及主要实现类
public interface Invoker<T> extends Node {
// 服务的interface
Class<T> getInterface();
//调用服务
Result invoke(Invocation invocation) throws RpcException;
}
invoke方法就是通过动态代理的机制,来调用远程服务。
(引入:
Invocation封装了调用的服务的信息、参数。
//invocation封装了调用远程方法的信息
public class RpcInvocation implements Invocation, Serializable {
private static final long serialVersionUID = -4355285085441097045L;
private String methodName;
private Class<?>[] parameterTypes;
private Object[] arguments;
private Map<String, String> attachments;
//当前context下的Invoker
private transient Invoker<?> invoker;
//后面省略属性的getter/setter方法
……
)
Invoker继承结构:
方框内为主要用到的Invoker。
- AbstractProxyInvoker 本地执行类的Invoker,实际通过Java反射的方式执行原始对象的方法。为proxyFactory.getInvoker生成的被wrapper包装过的Invoker-------InvokerWrapper。
- AbstractInvoker: 远程通信类的Invoker,实际通过通信协议发起远程调用请求,并接收响应。
- AbstraceClusterInvoker 多个远程通信类的Invoker聚合成的集群版Invoker,加入了集群容错和负载均衡策略。cluster集群下的Invoker实现,采用模板方法设计模式,abstract定义方法框架,具体方法实现由子类实现。
1 RegistryDirectory$InvokerDelegate
public class RegistryDirectory<T> extends AbstractDirectory<T> implements NotifyListener {
/**
* 代理类,主要用于存储注册中心下发的url地址,用于重新refer时能够根据providerURL queryMap overrideMap重新组装
*/
private static class InvokerDelegete<T> extends InvokerWrapper<T>{
private URL providerUrl;
public InvokerDelegete(Invoker<T> invoker, URL url, URL providerUrl) {
super(invoker, url);
this.providerUrl = providerUrl;
}
public URL getProviderUrl() {
return providerUrl;
}
}
}
public class InvokerWrapper<T> implements Invoker<T> {
private final Invoker<T> invoker;
private final URL url;
//含有带参数的构造方法,该类是个wrapper机制的包装类
public InvokerWrapper(Invoker<T> invoker, URL url){
this.invoker = invoker;
this.url = url;
}
invokerDelegate代理类,是RegistryDirectory.doList中获取的invoker实例类型,且有三个参数:
providerUrl:存储注册中心下,providerUrl存入的服务地址。
invoker:为包裹的服务类invoker——在debug中,该类为listenerInvokerWrapper类。
ur:
2 ListenerInvokerWrapper
public class ListenerInvokerWrapper<T> implements Invoker<T> {
private final Invoker<T> invoker;
//添加一组invokerListener监听器(该listener提供了referred和destroy两个方法,分别在invoker被调用和销毁时候调用)
private final List<InvokerListener> listeners;
public ListenerInvokerWrapper(Invoker<T> invoker, List<InvokerListener> listeners){
if (invoker == null) {
throw new IllegalArgumentException("invoker == null");
}
this.invoker = invoker;
this.listeners = listeners;
//当ListenerInvokerWrapper构造时,会触发所有的listener出发referred(监听到invoker被调用,执行对应方法)
if (listeners != null && listeners.size() > 0) {
for (InvokerListener listener : listeners) {
if (listener != null) {
try {
listener.referred(invoker);
} catch (Throwable t) {
logger.error(t.getMessage(), t);
}
}
}
}
}
public Class<T> getInterface() {
return invoker.getInterface();
}
public URL getUrl() {
return invoker.getUrl();
}
public boolean isAvailable() {
return invoker.isAvailable();
}
public Result invoke(Invocation invocation) throws RpcException {
return invoker.invoke(invocation);
}
public void destroy() {
try {
invoker.destroy();
} finally {
if (listeners != null && listeners.size() > 0) {
for (InvokerListener listener : listeners) {
if (listener != null) {
try {
listener.destroyed(invoker);
} catch (Throwable t) {
logger.error(t.getMessage(), t);
}
}
}
}
}
}
}
invokerListener:invoker的被调用或被销毁监听器
@SPI
public interface InvokerListener {
/**
* 当invoker被referred调用时,执行该方法
*
* @see com.alibaba.dubbo.rpc.Protocol#refer(Class, URL)
* @param invoker
* @throws RpcException
*/
void referred(Invoker<?> invoker) throws RpcException;
/**
* The invoker destroyed.
*
* @see com.alibaba.dubbo.rpc.Invoker#destroy()
* @param invoker
*/
void destroyed(Invoker<?> invoker);
}
7.3.2.2 DUBBO的核心-invoker转换
详见[6.3.2 Dubbo中Invoker的转换](#6.3.2 Dubbo中Invoker的转换)
7.3.3 Protocol
作用(理解):
在服务消费方,消费方的Invoker用于执行远程调用。invoker是由protocol实现类构建而来。
在服务的服务端,暴露本地服务通过动态代理生成的Invoker为exporter。
在消费端调用refer返回的Invoker.invoke时,protocol协议需要执行URL远端的export传入的Invoker.invoke方法。————protocol位于server端和client两端,实现远程调用的核心作用
protocol最常用的是RegistryProtocol和DubboProtocol。
理解protocol的逻辑功能
protocol是dubbo的协议层,提供了export(暴露)和refer(引用)两个方法。
1
用在服务端,用来暴露远程服务(就是server端的本地服务),将Invoker对象通过协议暴露给外部。
传入的Invoker是dubbo框架本身实现并传入的,protocol协议无需关心实现。对于dubbo,服务端的Invoker,是通过wrapper机制,动态代理的原理生成服务类。详见[Invoker的服务端转换](#5.3.2.2 DUBBO的核心-invoker转换 )。服务端接到请求,需要记录请求的address;其次,export应该是幂等的。
2
用在消费端,用来引用远程的服务,通过clazz、url等信息创建远程服务的动态代理Invoker。
type是服务的类型,url为远程服务地址,refer返回的Invoker对象,是由protocol协议实现的,其内包装了nettyClient的通信功能,协议调用远程服务,需要通过该Invoker发送远程请求。
在消费端调用refer返回的Invoker.invoke时,protocol协议需要执行URL远端的export传入的Invoker.invoke方法。————protocol位于server端和client两端,实现远程调用的核心作用
服务端的Invoker生成,详见[Invoker的服务端转换](#7.3.2.2 DUBBO的核心-invoker转换 )。
@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();
}
7.3.3.1 DubboProtocol
public class DubboProtocol extends AbstractProtocol {
//获取DubboInvoker实例
public <T> Invoker<T> refer(Class<T> serviceType, URL url) throws RpcException {
// create rpc invoker.
DubboInvoker<T> invoker = new DubboInvoker<T>(serviceType, url, getClients(url), invokers);
invokers.add(invoker);
return invoker;
}
//获取ExchangeClient客户端
private ExchangeClient[] getClients(URL url){
//是否共享连接
boolean service_share_connect = false;
int connections = url.getParameter(Constants.CONNECTIONS_KEY, 0);
//如果connections不配置,则共享连接,否则每服务每连接
if (connections == 0){
service_share_connect = true;
connections = 1;
}
ExchangeClient[] clients = new ExchangeClient[connections];
for (int i = 0; i < clients.length; i++) {
if (service_share_connect){
clients[i] = getSharedClient(url);
} else {
clients[i] = initClient(url);
}
}
return clients;
}
7.3.3.2 RegistryProtocol--todo
public class RegistryProtocol implements Protocol {
//对于@SPI属性,在registryProtocol用extensionLoader获取时,依赖注入对应的adpative对象
private Cluster cluster;
//进行实际暴露的protocol对象---protocol@Adpative
private Protocol protocol;
private RegistryFactory registryFactory;
private ProxyFactory proxyFactory;
//将服务URL注册入注册中心的RegistryProtocol
private static RegistryProtocol INSTANCE;
public RegistryProtocol() {
INSTANCE = this;
}
public static RegistryProtocol getRegistryProtocol() {
if (INSTANCE == null) {
ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(Constants.REGISTRY_PROTOCOL); // load
}
return INSTANCE;
}
//进行override配置时,即收到服务变更通知时触发
private final Map<URL, NotifyListener> overrideListeners = new ConcurrentHashMap<URL, NotifyListener>();
public Map<URL, NotifyListener> getOverrideListeners() {
return overrideListeners;
}
//用于解决rmi重复暴露端口冲突的问题,已经暴露过的服务不再重新暴露
//providerurl <--> exporter
//providerurl为服务端提供者的URL(dubbo://)---->ExporterChangeableWrapper内部类(记录originInvoker与protocol.export的关系)
private final Map<String, ExporterChangeableWrapper<?>> bounds = new ConcurrentHashMap<String, ExporterChangeableWrapper<?>>();
//内部类---记录protocol.export暴露出的exporter与原本originInvoker的对应关系。在override时,修改对应关系
private class ExporterChangeableWrapper<T> implements Exporter<T>{
private Exporter<T> exporter;
private final Invoker<T> originInvoker;
public ExporterChangeableWrapper(Exporter<T> exporter, Invoker<T> originInvoker){
this.exporter = exporter;
this.originInvoker = originInvoker;
}
public Invoker<T> getOriginInvoker() {
return originInvoker;
}
public Invoker<T> getInvoker() {
return exporter.getInvoker();
}
public void setExporter(Exporter<T> exporter){
this.exporter = exporter;
}
public void unexport() {
String key = getCacheKey(this.originInvoker);
bounds.remove(key);
exporter.unexport();
}
}
7.3.3.3 Protocol(wrapper机制)
因此,根据dubbo的wrapper机制,会在getExtension(name)时,依次wrap上filter、listener,就得到了包装后的protocol对象。
区别:
ProtocolListenerWrapper:通过ExporterListener,对exporter服务的暴露和下线进行消息通知;
ProtocolFilterWrapper:通过获取激活的filter,构造成invoker链,在调用服务方法时,通过around增强,进行功能拓展。
总结二者详细区别:
Protocol包装类 | ProtocolListenerWrapper | ProtocolFilterWrapper |
---|---|---|
对应的filter或listener数量 | exporterListener监听器数量少 | filter过滤器较多,可以做dubbo功能拓展 |
调用时机 | 服务进行exporte、unexport时 | 服务调用时执行 |
场景 | 消息通知服务暴露、下线 | 定制自动激活的Filter,在RPC调用时,拓展功能 |
类比AOP | after advice--服务暴露或下线后调用listener的方法 | around advice增强(filter在调用前后,执行filter逻辑) |
组织形式 | 遍历exporter对应的listener的执行 | RPC调用服务时,经过拦截器的链式处理 |
1 ProtocolListenerWrapper(对服务export/unexport消息通知)
Protocol的wrapper机制,包裹由外到内为ProtocolListenerWrapper->ProtocolFilterWrapper->XXXProtocol
public class ProtocolListenerWrapper implements Protocol {
//protocol的包装类
private final Protocol protocol;
public ProtocolListenerWrapper(Protocol protocol){
if (protocol == null) {
throw new IllegalArgumentException("protocol == null");
}
this.protocol = protocol;
}
public int getDefaultPort() {
return protocol.getDefaultPort();
}
public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
return protocol.export(invoker);
}
//暴露服务,并使用ExporterListener对暴露的服务进行监听
return new ListenerExporterWrapper<T>(protocol.export(invoker),
Collections.unmodifiableList(ExtensionLoader.getExtensionLoader(ExporterListener.class)
.getActivateExtension(invoker.getUrl(), Constants.EXPORTER_LISTENER_KEY)));
}
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
return protocol.refer(type, url);
}
return new ListenerInvokerWrapper<T>(protocol.refer(type, url),
Collections.unmodifiableList(
ExtensionLoader.getExtensionLoader(InvokerListener.class)
.getActivateExtension(url, Constants.INVOKER_LISTENER_KEY)));
}
public void destroy() {
protocol.destroy();
}
}
2 ProtocolFilterWrapper(构造拦截器链)
Protocol的wrapper机制,包裹由外到内为ProtocolListenerWrapper->ProtocolFilterWrapper->XXXProtocol
public class ProtocolFilterWrapper implements Protocol {
//protocol的包装类(dubbo的Wrapper机制)
private final Protocol protocol;
public ProtocolFilterWrapper(Protocol protocol){
if (protocol == null) {
throw new IllegalArgumentException("protocol == null");
}
this.protocol = protocol;
}
public int getDefaultPort() {
return protocol.getDefaultPort();
}
//暴露服务时,构造拦截器链
public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
return protocol.export(invoker);
}
return protocol.export(buildInvokerChain(invoker, Constants.SERVICE_FILTER_KEY, Constants.PROVIDER));
}
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
return protocol.refer(type, url);
}
return buildInvokerChain(protocol.refer(type, url), Constants.REFERENCE_FILTER_KEY, Constants.CONSUMER);
}
public void destroy() {
protocol.destroy();
}
//获取@active的filter,并将其构造成invoker链,链末尾是实际服务的Invoker
private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) {
Invoker<T> last = invoker;
//获取已经自动激活的filter对象
List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group);
if (filters.size() > 0) {
//倒序遍历filter,最后一个filter所构造的invoker,执行invoke时,是filter.invoke(next,invocation)。
for (int i = filters.size() - 1; i >= 0; i --) {
final Filter filter = filters.get(i);
final Invoker<T> next = last;
//将filter构造为invoker
last = new Invoker<T>() {
/** ……………………………………………将filter构造为invoker拦截器链,其方法,获取都是当前abstractProxyInvoker匿名类的属性…………………………………………*/
public Class<T> getInterface() {
return invoker.getInterface();
}
public URL getUrl() {
return invoker.getUrl();
}
public boolean isAvailable() {
return invoker.isAvailable();
}
public void destroy() {
invoker.destroy();
}
@Override
public String toString() {
return invoker.toString();
}
/**………………………………………………………………………………………………………………………链式调用的实现………………………………………………………………………………………………………………………… */
public Result invoke(Invocation invocation) throws RpcException {
return filter.invoke(next, invocation);
}
};
}
}
return last;
}
}
7.3.4 Exporter
作用(理解):
维护Invoker的生命周期,内部包含Invoker或者ExporterMap。
exporter作为暴露出的Invoker的服务的包装形式。提供了getInvoker方法获取暴露的Invoker服务;最主要提供了unexport方法,来取消暴露的服务。
public interface Exporter<T> {
//获取暴露的Invoker服务
Invoker<T> getInvoker();
/**
* 取消暴露Invoker
* <p>
* <code>
* getInvoker().destroy();
* </code>
*/
void unexport();
}
7.3.4.3 ListenerExporterWrapper
public class ListenerExporterWrapper<T> implements Exporter<T> {
private static final Logger logger = LoggerFactory.getLogger(ListenerExporterWrapper.class);
private final Exporter<T> exporter;
//暴露的exporter服务,对应的监听器ExporterListener
private final List<ExporterListener> listeners;
//构造函数,会在创建时候,遍历执行ExporterListener.exported(this)
public ListenerExporterWrapper(Exporter<T> exporter, List<ExporterListener> listeners){
if (exporter == null) {
throw new IllegalArgumentException("exporter == null");
}
this.exporter = exporter;
this.listeners = listeners;
if (listeners != null && listeners.size() > 0) {
RuntimeException exception = null;
for (ExporterListener listener : listeners) {
if (listener != null) {
try {
listener.exported(this);
} catch (RuntimeException t) {
logger.error(t.getMessage(), t);
exception = t;
}
}
}
if (exception != null) {
throw exception;
}
}
}
public Invoker<T> getInvoker() {
return exporter.getInvoker();
}
public void unexport() {
try {
exporter.unexport();
} finally {
if (listeners != null && listeners.size() > 0) {
RuntimeException exception = null;
for (ExporterListener listener : listeners) {
if (listener != null) {
try {
listener.unexported(this);
} catch (RuntimeException t) {
logger.error(t.getMessage(), t);
exception = t;
}
}
}
if (exception != null) {
throw exception;
}
}
}
}
}