七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封装了调用的服务的信息、参数。

image-20211014122010347

//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继承结构:

image-20211014122405410

方框内为主要用到的Invoker。

image-20220902102149739

  • 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实例类型,且有三个参数:

image-20221013135415821

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两端,实现远程调用的核心作用

image-20210909145707422

protocol最常用的是RegistryProtocol和DubboProtocol。

理解protocol的逻辑功能

protocol是dubbo的协议层,提供了export(暴露)和refer(引用)两个方法。

1 Exporter export(Invoker invoker)

用在服务端,用来暴露远程服务(就是server端的本地服务),将Invoker对象通过协议暴露给外部。

传入的Invoker是dubbo框架本身实现并传入的,protocol协议无需关心实现。对于dubbo,服务端的Invoker,是通过wrapper机制,动态代理的原理生成服务类。详见[Invoker的服务端转换](#5.3.2.2 DUBBO的核心-invoker转换 )。服务端接到请求,需要记录请求的address;其次,export应该是幂等的。

2 Invoker refer(Class type, URL url) ——初始化

用在消费端,用来引用远程的服务,通过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机制)

image-20221216200250632

因此,根据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

image-20221216195302843

image-20221216194736144

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

image-20221216195308054

image-20221216194752130

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方法,来取消暴露的服务。

image-20220830112119697

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;
                }
            }
        }
    }

}
posted @ 2023-03-13 14:54  LeasonXue  阅读(143)  评论(0编辑  收藏  举报