Dubbo源码—3.服务引用时执行RPC的流程一

大纲

1.对动态代理接口的方法进行调用时的入口

2.动态代理基于Invoker执行RPC调用

3.服务发现获取目标服务实例集群Invokers

4.DynamicDirectory进行服务发现的流程

5.构造DubboInvoker并建立网络连接的过程

6.LoadBalance的负载均衡机制

7.Dubbo进行RPC调用时的异步执行过程

8.Dubbo进行RPC调用后会如何等待响应

9.NettyServer会如何调用本地代码

10.Dubbo的分层架构原理

1.对动态代理接口的方法进行调用时的入口

当执行完Reference的get()方法生成动态代理的接口后,就可以调用接口的方法了。

当动态代理的接口方法被调用时,会进入InvokerInvocationHandler的invoke()方法中。

java 复制代码
public class Application {
    public static void main(String[] args) throws Exception {
        //Reference和ReferenceConfig是什么
        //Reference是一个引用,是对Provider端的一个服务实例的引用
        //ReferenceConfig这个服务实例的引用的一些配置
        //通过泛型传递了这个服务实例对外暴露的接口
        ReferenceConfig<DemoService> reference = new ReferenceConfig<>();

        //设置应用名称
        reference.setApplication(new ApplicationConfig("dubbo-demo-api-consumer"));

        //设置注册中心的地址,默认是ZooKeeper
        reference.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181"));

        //设置元数据上报地址
        reference.setMetadataReportConfig(new MetadataReportConfig("zookeeper://127.0.0.1:2181"));

        //设置要调用的服务的接口
        reference.setInterface(DemoService.class);

        //直接通过ReferenceConfig的get()方法来拿到一个DemoService接口
        //它是一个动态代理接口,只要被调用,便会通过底层调用Provider服务实例的对应接口
        DemoService service = reference.get();

        //下面调用动态代理的接口
        //会进入InvokerInvocationHandler的invoke()方法中
        String message = service.sayHello("dubbo");

        System.out.println(message);
        Thread.sleep(10000000L);
    }
}

//实现了JDK反射机制里的InvocationHandler接口
public class InvokerInvocationHandler implements InvocationHandler {
    ...
    public InvokerInvocationHandler(Invoker<?> handler) {
        this.invoker = handler;
        URL url = invoker.getUrl();
        this.protocolServiceKey = url.getProtocolServiceKey();
        this.serviceModel = url.getServiceModel();
    }

    //通过这个代理对象可以拿到这个代理对象的接口
    //通过接口就可以定位到目标服务实例发布的服务接口,从而针对目标服务实例进行调用
    //拿到了调用目标服务实例的方法、传递进去的参数等信息,就可以进行完整的RPC调用
    //动态代理就是针对接口动态去生成该接口的实现类并进行调用

    //比如针对DemoService这个接口去生成一个实现类
    //由于这个实现类是动态生成的,那么它如何知道会有调用方去调用它的方法,以及又如何去执行?

    //为此,动态代理底层都会封装InvocationHandler
    //封装完后对动态代理所有方法的调用,都会跑到InvocationHandler这里来

    //这样,InvocationHandler的invoke方法就可以拿到:
    //Proxy动态代理对象、需要调用对象的哪个方法Method、以及被调用方法会传入的参数args

    //此时,对动态代理不同方法的调用以及具体方法被调用后会如何处理
    //都可以由如下invoke()方法发起远程调用由服务提供者来决定
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //对于Object中定义的方法,直接调用Invoker对象的相应方法即可
        if (method.getDeclaringClass() == Object.class) {
            return method.invoke(invoker, args);
        }
        String methodName = method.getName();
        Class<?>[] parameterTypes = method.getParameterTypes();
        if (parameterTypes.length == 0) {
            if ("toString".equals(methodName)) {
                //对toString()方法进行特殊处理
                return invoker.toString();
            } else if ("$destroy".equals(methodName)) {
                //对$destroy等方法的特殊处理
                invoker.destroy();
                return null;
            } else if ("hashCode".equals(methodName)) {
                //对hashCode()方法进行特殊处理
                return invoker.hashCode();
            }
        } else if (parameterTypes.length == 1 && "equals".equals(methodName)) {
            return invoker.equals(args[0]);
        }

        //创建RpcInvocation对象,后面会作为远程RPC调用的参数
        //Consumer端进行RPC调用时,必须要封装一个RpcInvocation
        //这个RpcInvocation会传递到Provider端
        //Provider端拿到请求数据后,也会封装一个RpcInvocation
        RpcInvocation rpcInvocation = new RpcInvocation(serviceModel, method.getName(), invoker.getInterface().getName(), protocolServiceKey, method.getParameterTypes(), args);

        if (serviceModel instanceof ConsumerModel) {
            rpcInvocation.put(Constants.CONSUMER_MODEL, serviceModel);
            rpcInvocation.put(Constants.METHOD_MODEL, ((ConsumerModel) serviceModel).getMethodModel(method));
        }

        //调用invoke()方法发起远程调用
        //拿到AsyncRpcResult之后,调用recreate()方法获取响应结果(或是Future)
        //下面的invoker其实就是装饰了MockClusterInvoker的MigrationInvoker
        return InvocationUtil.invoke(invoker, rpcInvocation);
    }
}

public class InvocationUtil {
    public static Object invoke(Invoker<?> invoker, RpcInvocation rpcInvocation) throws Throwable {
        ...
        //为什么要进行recreate?
        //recreate是为了对拿到的结果进行一个拷贝,将拷贝出来的结果对象返回给业务方去使用
        //这样Dubbo框架内部自己可以持有一个结果对象,避免了和业务方共享持有和访问,而产生相互的影响
        return invoker.invoke(rpcInvocation).recreate();
    }
}

2.动态代理基于Invoker执行RPC调用

InvokerInvocationHandler的invoke()方法会调用InvocationUtil的invoke()方法,而后者又会返回"invoker.invoke(rpcInvocation).recreate()"的结果。其中,这个invoker是装饰了MockClusterInvoker的MigrationInvoker。所以,调用MigrationInvoker的invoke()方法时,会调用MockClusterInvoker的invoke()方法。

最终会调用AbstractClusterInvoker的invoke()方法,该方法会根据invocation信息列出所有的Invoker,也就是通过DynamicDirectory的list()方法进行服务发现,从而列出有哪些服务实例和有哪些Invoker,其中一个服务实例会对应一个Invoker。

arduino 复制代码
//-> InvokerInvocationHandler.invoke()
//-> InvocationUtil.invoke()
//   invoker.invoke(rpcInvocation).recreate()
//-> MigrationInvoker.invoke()
//-> MockClusterInvoker.invoke()
//-> AbstractCluster.ClusterFilterInvoker.invoke()
//-> FilterChainBuilder.CallbackRegistrationInvoker.invoke()
//-> FilterChainBuilder.CopyOfFilterChainNode.invoke()
//-> ConsumerContextFilter.invoke()
//-> FilterChainBuilder.CopyOfFilterChainNode.invoke()
//-> FutureFilter.invoke()
//-> FilterChainBuilder.CopyOfFilterChainNode.invoke()
//-> MonitorFilter.invoke()
//-> FilterChainBuilder.CopyOfFilterChainNode.invoke()
//-> RouterSnapshotFilter.invoke()
//-> AbstractClusterInvoker.invoke()
//-> AbstractClusterInvoker.list()
//-> DynamicDirectory.list()
//-> FailoverClusterInvoker.doInvoke()
java 复制代码
public class InvocationUtil {
    public static Object invoke(Invoker<?> invoker, RpcInvocation rpcInvocation) throws Throwable {
        ...
        //调用invoke()方法发起远程调用
        //拿到AsyncRpcResult之后,调用recreate()方法获取响应结果(或是Future)
        //下面的invoker其实就是装饰了MockClusterInvoker的MigrationInvoker
        return invoker.invoke(rpcInvocation).recreate();
    }
}

public class MigrationInvoker<T> implements MigrationClusterInvoker<T> {
    //服务引用时,它是一个MockClusterInvoker
    private volatile ClusterInvoker<T> invoker;
    //这是一个名为serviceDiscoveryInvoker的ClusterInvoker实现类的实例,也是一个MockClusterInvoker
    private volatile ClusterInvoker<T> serviceDiscoveryInvoker;
    //服务引用时,它是一个MockClusterInvoker
    private volatile ClusterInvoker<T> currentAvailableInvoker;
    ...

    //真正在执行Invoker调用时,可以在这里看到MigrationInvoker里的逻辑
    //为什么会叫MigrationInvoker?因为MigrationInvoker有两个Invoker:一个是invoker,一个是serviceDiscoveryInvoker
    //执行这里的invoke()方法时会根据不同的条件去切换这两个invoker,将它们之一赋值给真正负责执行invoke()方法的currentAvailableInvoker
    //也就是有一个针对currentAvailableInvoker进行切换的过程(根据不同的条件来切换是invoker还是serviceDiscoveryInvoker),所以migration就是从这里来的
    @Override
    public Result invoke(Invocation invocation) throws RpcException {
        ...
        //check if invoker available for each time
        return decideInvoker().invoke(invocation);
    }

    private ClusterInvoker<T> decideInvoker() {
        if (currentAvailableInvoker == serviceDiscoveryInvoker) {
            if (checkInvokerAvailable(serviceDiscoveryInvoker)) {
                return serviceDiscoveryInvoker;
            }
            return invoker;
        } else {
            return currentAvailableInvoker;
        }
    }

    public boolean checkInvokerAvailable(ClusterInvoker<T> invoker) {
        //其实就是调用MockClusterInvoker的isAvailable()来检查是否可用
        return invoker != null && !invoker.isDestroyed() && invoker.isAvailable();
    }
    ...
}

public class MockClusterInvoker<T> implements ClusterInvoker<T> {
    private final Directory<T> directory;
    private final Invoker<T> invoker;

    public MockClusterInvoker(Directory<T> directory, Invoker<T> invoker) {
        //传入的directory为DynamicDirectory
        //当初始化MigrationInvoker.invoker时,传入的directory为RegistryDirectory
        //当初始化MigrationInvoker.serviceDiscoveryInvoker时,传入的directory为ServiceDiscoveryRegistryDirectory
        //不管是RegistryDirectory,还是ServiceDiscoveryRegistryDirectory,其实都是DynamicDirectory
        this.directory = directory;
        ///传入的invoker为AbstractCluster的内部类ClusterFilterInvoker
        //其filterInvoker属性的originalInvoker属性便为封装了DynamicDirectory的FailoverClusterInvoker
        this.invoker = invoker;
    }

    @Override
    public boolean isAvailable() {
        return directory.isAvailable();
    }

    @Override
    public Result invoke(Invocation invocation) throws RpcException {
        ...
        //这里会直接发起正常的调用
        //每一层Invoker都会去负责自己的事情,对Invoker的调用使用了严格的责任链模式,运用了责任链模式的思想
        //A Invoker->B Invoker->C Invoker->D Invoker
        //在发起RPC调用时,由于会涉及到很多的机制,比如降级调用机制(mock),集群容错机制,负载均衡机制等
        //此时如果只有一个Invoker,那么它里面的代码就会很多很复杂,所以才用上了责任链模式
        //下面会调用AbstractCluster内部类ClusterFilterInvoker的invoke()方法,进行正常的RPC调用
        result = this.invoker.invoke(invocation);
        ...
        return result;
    }
    ...
}

public abstract class AbstractCluster implements Cluster {
    ...
    static class ClusterFilterInvoker<T> extends AbstractClusterInvoker<T> {
        ...
        @Override
        public Result invoke(Invocation invocation) throws RpcException {
            //下面会调用FilterChainBuilder的内部类CallbackRegistrationInvoker的invoke()方法
            return filterInvoker.invoke(invocation);
        }
        ...
    }
    ...
}

@SPI(value = "default", scope = APPLICATION)
public interface FilterChainBuilder {
    ...
    class CallbackRegistrationInvoker<T, FILTER extends BaseFilter> implements Invoker<T> {
        final Invoker<T> filterInvoker;
        final List<FILTER> filters;

        public CallbackRegistrationInvoker(Invoker<T> filterInvoker, List<FILTER> filters) {
            //这是一个CopyOfFilterChainNode
            this.filterInvoker = filterInvoker;
            //[ConsumerContextFilter, FutureFilter, MonitorFilter, RouterSnapshotFilter]
            this.filters = filters;
        }

        public Result invoke(Invocation invocation) throws RpcException {
            //下面首先会调用FilterChainBuilder$CopyOfFilterChainNode.invoke()
            Result asyncResult = filterInvoker.invoke(invocation);
            ...
        }
        ...
    }

    class CopyOfFilterChainNode<T, TYPE extends Invoker<T>, FILTER extends BaseFilter> implements Invoker<T> {
        ...
        @Override
        public Result invoke(Invocation invocation) throws RpcException {
            Result asyncResult;
            try {
                InvocationProfilerUtils.enterDetailProfiler(invocation, () -> "Filter " + filter.getClass().getName() + " invoke.");
                //比如Consumer端处理时下面会调用ConsumerContextFilter的invoke()方法
                //Provider端处理时下面会最终调用AbstractProxyInvoker.invoke()方法
                asyncResult = filter.invoke(nextNode, invocation);
            } catch (Exception e) {
                ...
            }
            ...
        }
        ...
    }
    ...
}

@Activate(group = CONSUMER, order = Integer.MIN_VALUE)
public class ConsumerContextFilter implements ClusterFilter, ClusterFilter.Listener {
    ...
    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        ...
        //下面又会调用FilterChainBuilder的内部类CopyOfFilterChainNode的invoke()方法
        return invoker.invoke(invocation);
    }
    ...
}

@Activate(group = CommonConstants.CONSUMER)
public class FutureFilter implements ClusterFilter, ClusterFilter.Listener {
    ...
    @Override
    public Result invoke(final Invoker<?> invoker, final Invocation invocation) throws RpcException {
        //触发invoker调用的回调
        fireInvokeCallback(invoker, invocation);
        //下面又会调用FilterChainBuilder的内部类CopyOfFilterChainNode的invoke()方法
        return invoker.invoke(invocation);
    }
    ...
}

@Activate(group = {PROVIDER})
public class MonitorFilter implements Filter, Filter.Listener {
    ...
    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        if (invoker.getUrl().hasAttribute(MONITOR_KEY)) {
            invocation.put(MONITOR_FILTER_START_TIME, System.currentTimeMillis());
            invocation.put(MONITOR_REMOTE_HOST_STORE, RpcContext.getServiceContext().getRemoteHost());
            //count up
            getConcurrent(invoker, invocation).incrementAndGet();
        }
        //proceed invocation chain
        //下面又会调用FilterChainBuilder的内部类CopyOfFilterChainNode的invoke()方法
        return invoker.invoke(invocation);
    }
    ...
}

@Activate(group = {CONSUMER})
public class RouterSnapshotFilter implements ClusterFilter, BaseFilter.Listener {
    ...
    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        //接下来会调用AbstractClusterInvoker的invoke()方法
        if (!switcher.isEnable()) {
            return invoker.invoke(invocation);
        }
        if (!logger.isInfoEnabled()) {
            return invoker.invoke(invocation);
        }
        if (!switcher.isEnable(invocation.getServiceModel().getServiceKey())) {
            return invoker.invoke(invocation);
        }
        RpcContext.getServiceContext().setNeedPrintRouterSnapshot(true);
        return invoker.invoke(invocation);
    }
    ...
}

public abstract class AbstractClusterInvoker<T> implements ClusterInvoker<T> {
    ...
    @Override
    public Result invoke(final Invocation invocation) throws RpcException {
        ...
        //下面会根据invocation信息列出所有的Invoker
        //也就是通过DynamicDirectory.list()方法进行服务发现
        //由于通过Directory获取Invoker对象列表
        //通过了解RegistryDirectory可知,其中已经调用了Router进行过滤
        //从而可以知道有哪些服务实例、有哪些Invoker
        //由于一个服务实例会对应一个Invoker,所以目标服务实例集群已变成invokers了
        List<Invoker<T>> invokers = list(invocation);
        InvocationProfilerUtils.releaseDetailProfiler(invocation);

        //通过SPI加载LoadBalance实例,也就是在这里选择出对应的负载均衡策略
        LoadBalance loadbalance = initLoadBalance(invokers, invocation);
        RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);

        InvocationProfilerUtils.enterDetailProfiler(invocation, () -> "Cluster " + this.getClass().getName() + " invoke.");
        try {
            //调用由子类实现的抽象方法doInvoke()
            //下面会由子类FailoverClusterInvoker执行doInvoke()方法
            return doInvoke(invocation, invokers, loadbalance);
        } finally {
            InvocationProfilerUtils.releaseDetailProfiler(invocation);
        }
    }

    protected List<Invoker<T>> list(Invocation invocation) throws RpcException {
        //通过DynamicDirectory.list()进行服务发现
        return getDirectory().list(invocation);
    }

    @Override
    public Directory<T> getDirectory() {
        return directory;
    }
    ...
}

public class FailoverClusterInvoker<T> extends AbstractClusterInvoker<T> {
    ...
    //该方法会找出一个Invoker
    //把invocation交给多个Invokers里的一个去发起RPC调用
    //其中会根据传入的loadbalance来实现负载均衡
    public Result doInvoke(Invocation invocation, final List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
        //下面先做一个引用赋值
        List<Invoker<T>> copyInvokers = invokers;
        //检查Invokers
        checkInvokers(copyInvokers, invocation);
        //从RPC调用里提取一个method方法名称,从而确定需要调用的是哪个方法
        String methodName = RpcUtils.getMethodName(invocation);
        //计算最多调用次数;因为Failover策略是,如果发现调用不成功会进行重试,但默认会最多调用3次来让调用成功
        int len = calculateInvokeTimes(methodName);
        //last exception.
        RpcException le = null;
        //构建了一个跟invokers数量相等的一个list
        List<Invoker<T>> invoked = new ArrayList<Invoker<T>>(copyInvokers.size());//invoked invokers.
        //基于计算出的调用次数,构建一个set;如果调用次数为3,那么意味着最多会调用3个provider服务实例
        Set<String> providers = new HashSet<String>(len);

        //对len次数进行循环
        for (int i = 0; i < len; i++) {
            //到i>0时,表示的是第一次调用失败,要开始进行重试了
            if (i > 0) {
                //检查当前服务实例是否被销毁
                checkWhetherDestroyed();
                //此时要调用DynamicDirectory进行一次invokers列表刷新
                //因为第一次调用都失败了,所以有可能invokers列表出现了变化,因而需要刷新一下invokers列表
                copyInvokers = list(invocation);
                //check again
                //再次check一下invokers是否为空
                checkInvokers(copyInvokers, invocation);
            }

            //1.下面会调用AbstractClusterInvoker的select()方法
            //select()方法会选择一个Invoker出来,具体逻辑是:
            //首先尝试用负载均衡算法去选
            //如果选出的Invoker是选过的或者不可用的,那么就直接reselect
            //也就是对选过的找一个可用的,对选不出的直接挑选下一个
            Invoker<T> invoker = select(loadbalance, invocation, copyInvokers, invoked);
            invoked.add(invoker);

            RpcContext.getServiceContext().setInvokers((List) invoked);
            boolean success = false;
            try {
                //2.调用AbstractClusterInvoker的invokeWithContext()方法
                //基于该Invoker发起RPC调用,并拿到一个result
                Result result = invokeWithContext(invoker, invocation);
                if (le != null && logger.isWarnEnabled()) {
                    logger.warn("...");
                }
                success = true;
                return result;
            } catch (RpcException e) {
                //如果本次RPC调用失败了,那么就会有异常抛出来
                if (e.isBiz()) {
                    throw e;
                }
                le = e;
            } catch (Throwable e) {
                le = new RpcException(e.getMessage(), e);
            } finally {
                if (!success) {
                    //下面会把出现RPC调用异常的进行设置,把本次调用失败的invoker地址添加到providers
                    providers.add(invoker.getUrl().getAddress());
                }
            }
        }

        //如果最后抛出如下这个异常,则说明本次RPC调用彻底失败了
        throw new RpcException("...");
    }
    ...
}

3.服务发现获取目标服务实例集群Invokers

服务发现获取目标服务实例集群Invokers的入口便是AbstractClusterInvoker的list()方法,该方法会调用AbstractDirectory的list()方法来获取目标服务实例集群。

在AbstractDirectory的list()方法中,可以发现目标服务实例集群invokers其实已经缓存在内存了,所以并没有直接去zk中进行获取。同时,该方法会根据缓存的目标服务实例集群invokers,调用AbstractDirectory的子类DynamicDirectory的doList()方法来获取合适的目标服务实例集群。

而在DynamicDirectory的doList()方法中,则会调用RouterChain的route()方法对目标服务实例集群进行过滤。

arduino 复制代码
//-> AbstractClusterInvoker.invoke()
//-> AbstractClusterInvoker.list()
//-> AbstractDirectory.list()
//-> DynamicDirectory.doList()
//-> RouterChain.route()
swift 复制代码
public abstract class AbstractClusterInvoker<T> implements ClusterInvoker<T> {
    protected Directory<T> directory;

    @Override
    public Result invoke(final Invocation invocation) throws RpcException {
        ...
        //下面会根据invocation信息列出所有的Invoker
        //也就是通过DynamicDirectory.list()方法进行服务发现
        //由于通过Directory获取Invoker对象列表
        //通过了解RegistryDirectory可知,其中已经调用了Router进行过滤
        //从而可以知道有哪些服务实例、有哪些Invoker
        //由于一个服务实例会对应一个Invoker,所以目标服务实例集群已变成invokers了
        List<Invoker<T>> invokers = list(invocation);
        InvocationProfilerUtils.releaseDetailProfiler(invocation);

        //通过SPI加载LoadBalance实例,也就是在这里选择出对应的负载均衡策略
        LoadBalance loadbalance = initLoadBalance(invokers, invocation);
        RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);

        InvocationProfilerUtils.enterDetailProfiler(invocation, () -> "Cluster " + this.getClass().getName() + " invoke.");
        try {
            //调用由子类实现的抽象方法doInvoke()
            //下面会由子类FailoverClusterInvoker执行doInvoke()方法
            return doInvoke(invocation, invokers, loadbalance);
        } finally {
            InvocationProfilerUtils.releaseDetailProfiler(invocation);
        }
    }

    protected List<Invoker<T>> list(Invocation invocation) throws RpcException {
        //通过DynamicDirectory.list()进行服务发现
        return getDirectory().list(invocation);
    }

    @Override
    public Directory<T> getDirectory() {
        return directory;
    }
    ...
}

public abstract class AbstractDirectory<T> implements Directory<T> {
    //All invokers from registry
    private volatile BitList<Invoker<T>> invokers = BitList.emptyList();
    //Valid Invoker. All invokers from registry exclude unavailable and disabled invokers.
    private volatile BitList<Invoker<T>> validInvokers = BitList.emptyList();
    ...

    @Override
    public List<Invoker<T>> list(Invocation invocation) throws RpcException {
        ...
        BitList<Invoker<T>> availableInvokers;
        //use clone to avoid being modified at doList().
        if (invokersInitialized) {
            availableInvokers = validInvokers.clone();
        } else {
            availableInvokers = invokers.clone();
        }
        List<Invoker<T>> routedResult = doList(availableInvokers, invocation);
        ...
    }

    protected abstract List<Invoker<T>> doList(BitList<Invoker<T>> invokers, Invocation invocation) throws RpcException;
    ...
}

public abstract class DynamicDirectory<T> extends AbstractDirectory<T> implements NotifyListener {
    ...
    @Override
    public List<Invoker<T>> doList(BitList<Invoker<T>> invokers, Invocation invocation) {
        if (forbidden && shouldFailFast) {
            //1. No service provider
            //2. Service providers are disabled
            throw new RpcException(RpcException.FORBIDDEN_EXCEPTION, "...");
        }
        if (multiGroup) {
            return this.getInvokers();
        }
        try {
            //Get invokers from cache, only runtime routers will be executed.
            //从缓存中获取invokers,只有运行中的routers才会被执行
            List<Invoker<T>> result = routerChain.route(getConsumerUrl(), invokers, invocation);
            return result == null ? BitList.emptyList() : result;
        } catch (Throwable t) {
            //2-1 - Failed to execute routing.
            logger.error(CLUSTER_FAILED_SITE_SELECTION, "", "", "Failed to execute router: " + getUrl() + ", cause: " + t.getMessage(), t);
            return BitList.emptyList();
        }
    }
    ...
}

public class RouterChain<T> {
    ...
    public List<Invoker<T>> route(URL url, BitList<Invoker<T>> availableInvokers, Invocation invocation) {
        if (RpcContext.getServiceContext().isNeedPrintRouterSnapshot()) {
            return routeAndPrint(url, availableInvokers, invocation);
        } else {
            return simpleRoute(url, availableInvokers, invocation);
        }
    }
    ...
}

在AbstractDirectory的list()方法中,会获取缓存中的invokers进行处理,那么缓存中的invokers究竟是什么时候从zk中获取并进行缓存的呢?

其实就是在服务引用时创建动态代理的过程中,通过调用DynamicDirectory的subscribe()方法,从zk中获取服务实例并进行缓存的,其中的调用链如下所示:

arduino 复制代码
//-> ReferenceConfig.get()
//-> ReferenceConfig.init()
//-> ReferenceConfig.createProxy() 
//-> ReferenceConfig.createInvokerForRemote() 
//-> protocolSPI.refer() 
//-> RegistryProtocol.refer()
//-> RegistryProtocol.doRefer()
//-> RegistryProtocol.interceptInvoker() 
//-> listener.onRefer()
//-> RegistryProtocol.getInvoker()
//-> RegistryProtocol.doCreateInvoker() 
//-> directory.subscribe(toSubscribeUrl(urlToRegistry))
typescript 复制代码
public class RegistryProtocol implements Protocol, ScopeModelAware {
    ...
    protected <T> ClusterInvoker<T> doCreateInvoker(DynamicDirectory<T> directory, Cluster cluster, Registry registry, Class<T> type) {
        ...
        //订阅服务,toSubscribeUrl()方法会将urlToRegistry中category参数修改为"providers,configurators,routers"
        //下面会调用DynamicDirectory子类RegistryDirectory的subscribe()会进行服务发现,同时还会添加相应的监听器
        //进行服务发现时,会把从注册中心拿到的服务实例集群invokers都初始化和缓存完毕
        //并对每个服务实例都新建NettyClient来和provider建立好网络连接
        //后面通过directory.list()获取服务实例集群invokers就会从缓存中获取了
        directory.subscribe(toSubscribeUrl(urlToRegistry));
        ...
    }
    ...
}

4.DynamicDirectory进行服务发现的流程

(1)subscribe()方法对服务订阅和发现

(2)doList()方法进行获取服务

(1)subscribe()方法对服务订阅和发现

bash 复制代码
//-> ReferenceConfig.get()
//-> RegistryProtocol.doCreateInvoker()
//-> directory.subscribe(toSubscribeUrl(urlToRegistry))
//-> RegistryDirectory.subscribe()
//-> DynamicDirectory.subscribe()
//-> ListenerRegistryWrapper.subscribe()
//-> FailbackRegistry.subscribe()
//-> AbstractRegistry.subscribe() + FailbackRegistry.doSubscribe()
//-> ZookeeperRegistry.doSubscribe() + create()/notify() [通过zkClient对服务进行订阅和监听]
//-> FailbackRegistry.notify() [通知NotifyListener处理当前已有的URL等注册数据]
//-> AbstractRegistry.notify()
//-> RegistryDirectory.notify() [期间会通过NettyClient和provider建立网络连接]
//-> RegistryDirectory.toInvokers()
//-> DubboProtocol.refer()
//-> DubboProtocol.protocolBindingRefer() [构建Invoker即封装一个DubboInvoker]
//-> DubboProtocol.getClients() [DubboInvoker的构建过程便会通过NettyClient对服务实例建立网络连接]
//-> DubboProtocol.initClient()
//-> Exchangers.connect()
//-> new DubboInvoker()
scala 复制代码
public class RegistryDirectory<T> extends DynamicDirectory<T> {
    private final ModuleModel moduleModel;
    private final ConsumerConfigurationListener consumerConfigurationListener;
    private ReferenceConfigurationListener referenceConfigurationListener;
    ...

    @Override
    public void subscribe(URL url) {
        //调用DynamicDirectory.subscribe()方法
        super.subscribe(url);
        if (moduleModel.getModelEnvironment().getConfiguration().convert(Boolean.class, org.apache.dubbo.registry.Constants.ENABLE_CONFIGURATION_LISTEN, true)) {
            //将当前RegistryDirectory对象作为ConfigurationListener记录到consumerConfigurationListener中
            consumerConfigurationListener.addNotifyListener(this);
            referenceConfigurationListener = new ReferenceConfigurationListener(moduleModel, this, url);
        }
    }
    ...
}

//DynamicDirectory相当于2.7.x里的RegistryDirectory
//它是一个用来进行服务发现的组件,是一个可以动态管理可变的服务实例集群地址的组件
//当Consumer调用Provider时,便会用到该动态目录DynamicDirectory进行服务发现

//动态目录可以理解为:
//动态可变的一个目标服务实例的集群地址(invokers)
//有多少个目标服务实例就会有多少Invoker

//动态的意思其实就是:
//不仅可以通过主动查询来获取目标服务实例集群地址
//还可以在目标服务实例集群地址发生变化时,接收zk的推送并更新内存里的地址

//DynamicDirectory有两个重要的方法:
//1.subscribe()
//2.doList()
public abstract class DynamicDirectory<T> extends AbstractDirectory<T> implements NotifyListener {
    ...
    public void subscribe(URL url) {
        setSubscribeUrl(url);
        //实现服务发现靠的就是下面这个方法
        //此时会调用ListenerRegistryWrapper.subscribe()方法
        registry.subscribe(url, this);
    }
    ...
}

public class ListenerRegistryWrapper implements Registry {
    //RegistryProtocol.export()方法中获取Registry时,这里会是一个ServiceDiscoveryRegistry
    //RegistryProtocol.refer() -> RegistryProtocol.doCreateInvoker()时,这里会是一个ZookeeperRegistry
    private final Registry registry;

    ...
    public void subscribe(URL url, NotifyListener listener) {
        ...
        //服务引用时下面会调用ZookeeperRegistry的父类FailbackRegistry的subscribe()方法
        //服务发布时下面会调用ServiceDiscoveryRegistry的subscribe()方法
        registry.subscribe(url, listener);
        ...
    }
    ...
}

public abstract class FailbackRegistry extends AbstractRegistry {
    ...
    public void subscribe(URL url, NotifyListener listener) {
        //先执行父类的订阅过程,也就是调用AbstractRegistry.subscribe()
        super.subscribe(url, listener);
        ...
        //然后调用ZookeeperRegistry.doSubscribe()方法
        doSubscribe(url, listener);
        ...
    }

    public abstract void doSubscribe(URL url, NotifyListener listener);
    ...
}

public abstract class AbstractRegistry implements Registry {
    ...
    @Override
    public void subscribe(URL url, NotifyListener listener) {
        ...
        //这个url是当前要订阅的地址,也就是要关注的那个服务接口
        //listener是那个服务的订阅监听,可能会施加多个监听器
        //这些监听器会被加入到subscribed中该url所对应的set里面
        //订阅和监听时,需要添加一个监听器,但这个NotifyListener并非是zk里面的监听器
        Set<NotifyListener> listeners = subscribed.computeIfAbsent(url, n -> new ConcurrentHashSet<>());
        listeners.add(listener);
    }
    ...
}

public class ZookeeperRegistry extends CacheableFailbackRegistry {
    ...
    public void doSubscribe(final URL url, final NotifyListener listener) {
        ...
        //create "directories".
        //尝试创建持久节点,主要是为了确保当前path在Zookeeper上存在
        //比如会对"/dubbo/服务接口/providers"进行检查,如果存在就不处理,如果不存在就去进行创建
        zkClient.create(root, false);

        //Add children (i.e. service items).
        //针对要订阅和发现的那个服务节点添加一个监听器
        //而且第一次加监听器,就会直接把子节点列表返回
        //这个子节点列表,就是指定的Provider服务实例集群地址列表
        List<String> children = zkClient.addChildListener(path, zkListener);
        ...

        //初次订阅时,会主动调用一次notify()方法,通知NotifyListener处理当前已有的URL等注册数据
        //这里会调用FailbackRegistry.notify()方法
        notify(url, listener, urls);
    }
    ...
}

//这是一个支持故障和重试的抽象类
public abstract class FailbackRegistry extends AbstractRegistry {
    ...
    protected void notify(URL url, NotifyListener listener, List<URL> urls) {
        //在订阅和发现时,必然需要直接定位到对应的Providers集群地址
        //所以这些地址需要存储在本地,这样才能方便后续通过directory获取,保证随时可以拿到对应的集群地址
        ...
        //FailbackRegistry的doNotify()方法实际上就是调用父类AbstractRegistry.notify()方法,没有其他逻辑
        doNotify(url, listener, urls);
        ...
    }

    protected void doNotify(URL url, NotifyListener listener, List<URL> urls) {
        //FailbackRegistry的doNotify()方法实际上就是调用父类AbstractRegistry.notify()方法,没有其他逻辑
        super.notify(url, listener, urls);
    }
    ...
}

public abstract class AbstractRegistry implements Registry {
    ...
    protected void notify(URL url, NotifyListener listener, List<URL> urls) {
        ...
        for (Map.Entry<String, List<URL>> entry : result.entrySet()) {
            String category = entry.getKey();
            List<URL> categoryList = entry.getValue();
            categoryNotified.put(category, categoryList);
            //下面会调用RegistryDirectory的notify()方法,通过NettyClient建立网络连接
            listener.notify(categoryList);
            ...
        }
    }
    ...
}

public class RegistryDirectory<T> extends DynamicDirectory<T> {
    ...
    public synchronized void notify(List<URL> urls) {
        //按照category进行分类,分成configurators、routers、providers三类
        Map<String, List<URL>> categoryUrls = urls.stream()
            .filter(Objects::nonNull)
            .filter(this::isValidCategory)
            .filter(this::isNotCompatibleFor26x)
            .collect(Collectors.groupingBy(this::judgeCategory));
        //获取configurators类型的URL,并转换成Configurator对象
        List<URL> configuratorURLs = categoryUrls.getOrDefault(CONFIGURATORS_CATEGORY, Collections.emptyList());
        this.configurators = Configurator.toConfigurators(configuratorURLs).orElse(this.configurators);
        //获取routers类型的URL,并转成Router对象,添加到RouterChain中
        List<URL> routerURLs = categoryUrls.getOrDefault(ROUTERS_CATEGORY, Collections.emptyList());
        toRouters(routerURLs).ifPresent(this::addRouters);
        //providers
        //获取providers类型的URL,调用refreshOverrideAndInvoker()方法进行处理
        List<URL> providerURLs = categoryUrls.getOrDefault(PROVIDERS_CATEGORY, Collections.emptyList());
        ...

        refreshOverrideAndInvoker(providerURLs);
    }

    private synchronized void refreshOverrideAndInvoker(List<URL> urls) {
        refreshInvoker(urls);
    }

    private void refreshInvoker(List<URL> invokerUrls) {
        ...
        //将invokerUrls转换为对应的Invoker映射关系
        Map<URL, Invoker<T>> newUrlInvokerMap = toInvokers(oldUrlInvokerMap, invokerUrls);
        ...
    }

    private Map<URL, Invoker<T>> toInvokers(Map<URL, Invoker<T>> oldUrlInvokerMap, List<URL> urls) {
        ...
        //这里通过Protocol.refer()方法创建对应的Invoker对象
        //比如首先会调用Protocol$Adaptive.refer()
        //然后调用ProtocolSerializationWrapper.refer()
        //接着调用ProtocolFilterWrapper.refer()
        //然后调用ProtocolListenerWrapper.refer()
        //最后调用DubboProtocol.refer()
        invoker = protocol.refer(serviceType, url);
        ...
    }
    ...
}

public class DubboProtocol extends AbstractProtocol {
    ...
    public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
        checkDestroyed();
        return protocolBindingRefer(type, url);
    }

    public <T> Invoker<T> protocolBindingRefer(Class<T> serviceType, URL url) throws RpcException {
        checkDestroyed();
        //进行序列化优化,注册需要优化的类
        optimizeSerialization(url);
        //create rpc invoker,创建DubboInvoker对象
        //首先将url传入getClients()方法中,针对目标服务实例进行网络连接
        //然后再根据这个目标服务实例的url,构建一个DubboInvoker
        DubboInvoker<T> invoker = new DubboInvoker<T>(serviceType, url, getClients(url), invokers);
        //将上面创建的DubboInvoker对象添加到invoker集合中
        invokers.add(invoker);
        return invoker;
    }

    private ExchangeClient[] getClients(URL url) {
        //CONNECTIONS_KEY参数值决定了后续建立连接的数量
        int connections = url.getParameter(CONNECTIONS_KEY, 0);
        //如果没有连接数的相关配置,默认使用共享连接的方式
        if (connections == 0) {
            //确定建立共享连接的条数,默认只建立一条共享连接
            String shareConnectionsStr = StringUtils.isBlank(url.getParameter(SHARE_CONNECTIONS_KEY, (String) null))
                ? ConfigurationUtils.getProperty(url.getOrDefaultApplicationModel(), SHARE_CONNECTIONS_KEY, DEFAULT_SHARE_CONNECTIONS)
                : url.getParameter(SHARE_CONNECTIONS_KEY, (String) null);
            connections = Integer.parseInt(shareConnectionsStr);

            //创建公共ExchangeClient集合
            List<ReferenceCountExchangeClient> shareClients = getSharedClient(url, connections);
            //整理要返回的ExchangeClient集合
            ExchangeClient[] clients = new ExchangeClient[connections];
            Arrays.setAll(clients, shareClients::get);
            return clients;
        }

        //整理要返回的ExchangeClient集合
        ExchangeClient[] clients = new ExchangeClient[connections];
        for (int i = 0; i < clients.length; i++) {
            //不使用公共连接的情况下,会创建单独的ExchangeClient实例
            clients[i] = initClient(url);
        }
        return clients;
    }

    private ExchangeClient initClient(URL url) {
        //获取客户端类型,并检查
        String str = url.getParameter(CLIENT_KEY, url.getParameter(SERVER_KEY, DEFAULT_REMOTING_CLIENT));
        if (StringUtils.isNotEmpty(str) && !url.getOrDefaultFrameworkModel().getExtensionLoader(Transporter.class).hasExtension(str)) {
            throw new RpcException("Unsupported client type: " + str + "," +
                " supported client type is " + StringUtils.join(url.getOrDefaultFrameworkModel().getExtensionLoader(Transporter.class).getSupportedExtensions(), " "));
        }
        try {
            url = new ServiceConfigURL(DubboCodec.NAME, url.getUsername(), url.getPassword(), url.getHost(), url.getPort(), url.getPath(), url.getAllParameters());
            //设置Codec2的扩展名
            url = url.addParameter(CODEC_KEY, DubboCodec.NAME);
            //设置默认的心跳间隔
            url = url.addParameterIfAbsent(HEARTBEAT_KEY, String.valueOf(DEFAULT_HEARTBEAT));
            //如果配置了延迟创建连接的特性,则创建LazyConnectExchangeClient
            //否则,调用Exchangers的connect()方法建立网络连接
            return url.getParameter(LAZY_CONNECT_KEY, false)
                ? new LazyConnectExchangeClient(url, requestHandler)
                : Exchangers.connect(url, requestHandler);
        } catch (RemotingException e) {
            throw new RpcException("Fail to create remoting client for service(" + url + "): " + e.getMessage(), e);
        }
    }
    ...
}

(2)doList()方法进行获取服务

kotlin 复制代码
public abstract class DynamicDirectory<T> extends AbstractDirectory<T> implements NotifyListener {
    ...
    @Override
    public List<Invoker<T>> doList(BitList<Invoker<T>> invokers, Invocation invocation) {
        if (forbidden && shouldFailFast) {
            //检测forbidden字段,当该字段在refreshInvoker()过程中设置为true时,表示无Provider可用,直接抛出异常
            //1.No service provider
            //2.Service providers are disabled
            throw new RpcException(RpcException.FORBIDDEN_EXCEPTION, "...");
        }

        if (multiGroup) {
            //multiGroup为true时的特殊处理
            //在refreshInvoker()方法中针对multiGroup为true的场景,已经使用Router进行了筛选,所以这里直接返回接口
            return this.getInvokers();
        }

        try {
            //会有很多种Router路由策略,比如TagRouter、ServiceRouter、AppRouter等;
            //当调用Provider时,就可以根据tag、service、app等各种配置进行筛选,把一些特定实例的provider筛选出来进行访问
            //比如灰度发布,对于Provider现在需要灰度发布一台新机器,跑的是新版本,而另外2台机器依旧是旧版本
            //这时就需要所提供的Provider服务,必须要能把请求分发给老版本的旧机器,而新版本的新机器则暂时还不能访问或者只分发一点点流量

            //Get invokers from cache, only runtime routers will be executed.
            //从缓存中获取invokers,只有运行中的routers才会被执行
            //也就是通过RouterChain.route()方法路由Invoker集合,最终得到符合路由条件的Invoker集合
            List<Invoker<T>> result = routerChain.route(getConsumerUrl(), invokers, invocation);
            return result == null ? BitList.emptyList() : result;
        } catch (Throwable t) {
            logger.error("Failed to execute router: " + getUrl() + ", because: " + t.getMessage(), t);
            return BitList.emptyList();
        }
    }
    ...
}

//Router chain
//路由链条其实就是一些路由规则
//通过这些路由规则的过滤,能够把可以用来访问的目标服务实例invokers筛选出来
//使用了责任链模式的链条有:filter链条,invoker链条,router链条
//会有很多种Router路由策略,比如TagRouter、ServiceRouter、AppRouter等
//当调用Provider时,就可以根据tag、service、app等各种配置进行筛选,把一些特定实例的provider筛选出来进行访问
//比如灰度发布,对于Provider现在需要灰度发布一台新机器,跑的是新版本,而另外2台机器依旧是旧版本
//这时就需要所提供的Provider服务,必须要能把请求分发给老版本的旧机器,而新版本的新机器则暂时还不能访问或者只分发一点点流量
public class RouterChain<T> {
    //当前RouterChain中要使用的Router集合
    private volatile List<Router> routers = Collections.emptyList();
    //RouterChain中的链表头节点
    private volatile StateRouter<T> headStateRouter;
    ...

    public List<Invoker<T>> route(URL url, BitList<Invoker<T>> availableInvokers, Invocation invocation) {
        if (RpcContext.getServiceContext().isNeedPrintRouterSnapshot()) {
            return routeAndPrint(url, availableInvokers, invocation);
        } else {
            return simpleRoute(url, availableInvokers, invocation);
        }
    }

    public List<Invoker<T>> simpleRoute(URL url, BitList<Invoker<T>> availableInvokers, Invocation invocation) {
        BitList<Invoker<T>> resultInvokers = availableInvokers.clone();

        //1.route state router
        //从头开始执行StateRouter链里的每个StateRouter的route()方法
        resultInvokers = headStateRouter.route(resultInvokers, url, invocation, false, null);
        if (resultInvokers.isEmpty() && (shouldFailFast || routers.isEmpty())) {
            printRouterSnapshot(url, availableInvokers, invocation);
            return BitList.emptyList();
        }

        if (routers.isEmpty()) {
            return resultInvokers;
        }
        List<Invoker<T>> commonRouterResult = resultInvokers.cloneToArrayList();

        //2.route common router
        //遍历routers字段,逐个调用Router对象的route()方法,对invokers集合进行过滤
        for (Router router : routers) {
            //Copy resultInvokers to a arrayList. BitList not support
            RouterResult<Invoker<T>> routeResult = router.route(commonRouterResult, url, invocation, false);
            commonRouterResult = routeResult.getResult();
            if (CollectionUtils.isEmpty(commonRouterResult) && shouldFailFast) {
                printRouterSnapshot(url, availableInvokers, invocation);
                return BitList.emptyList();
            }

            //stop continue routing
            if (!routeResult.isNeedContinueRoute()) {
                return commonRouterResult;
            }
        }

        if (commonRouterResult.isEmpty()) {
            printRouterSnapshot(url, availableInvokers, invocation);
            return BitList.emptyList();
        }

        return commonRouterResult;
    }
    ...
}

5.构造DubboInvoker并建立网络连接的过程

DubboProtocol的protocolBindingRefer()方法会先通过getClients()方法建立网络连接,然后才封装一个DubboInvoker对象进行返回。

arduino 复制代码
//-> ReferenceConfig.get()
//...
//-> DubboProtocol.refer()
//-> DubboProtocol.protocolBindingRefer()
//-> DubboProtocol.getClients()
//-> DubboProtocol.getSharedClient()
//-> DubboProtocol.buildReferenceCountExchangeClientList()
//-> DubboProtocol.buildReferenceCountExchangeClient()
//-> DubboProtocol.initClient()
//-> Exchangers.connect(url, requestHandler)
//-> getExchanger(url).connect(url, handler) 
//-> Exchanger.connect(url, handler)
//-> HeaderExchanger.connect()
//-> Transporters.connect()
//-> Transporters.getTransporter(url).connect(url, handler)
//-> NettyTransporter.connect()
//-> new NettyClient(url, handler) [构建NettyClient发起连接]
//-> new AbstractClient(url, handler)
//-> NettyClient.doOpen() + NettyClient.doConnect()
java 复制代码
public class DubboProtocol extends AbstractProtocol {
    //<host:port,Exchanger>
    //Map<String, List<ReferenceCountExchangeClient>
    private final Map<String, Object> referenceClientMap = new ConcurrentHashMap<>();
    ...

    public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
        checkDestroyed();
        return protocolBindingRefer(type, url);
    }

    public <T> Invoker<T> protocolBindingRefer(Class<T> serviceType, URL url) throws RpcException {
        checkDestroyed();
        //进行序列化优化,注册需要优化的类
        optimizeSerialization(url);
        //create rpc invoker,创建DubboInvoker对象
        //首先将url传入getClients()方法中,针对目标服务实例进行网络连接
        //然后再根据这个目标服务实例的url,构建一个DubboInvoker
        DubboInvoker<T> invoker = new DubboInvoker<T>(serviceType, url, getClients(url), invokers);
        //将上面创建的DubboInvoker对象添加到invoker集合中
        invokers.add(invoker);
        return invoker;
    }
        
    private ExchangeClient[] getClients(URL url) {
        //CONNECTIONS_KEY参数值决定了后续建立连接的数量
        int connections = url.getParameter(CONNECTIONS_KEY, 0);
        //如果没有连接数的相关配置,默认使用共享连接的方式
        if (connections == 0) {
            //确定建立共享连接的条数,默认只建立一条共享连接
            String shareConnectionsStr = StringUtils.isBlank(url.getParameter(SHARE_CONNECTIONS_KEY, (String) null))
                ? ConfigurationUtils.getProperty(url.getOrDefaultApplicationModel(), SHARE_CONNECTIONS_KEY, DEFAULT_SHARE_CONNECTIONS)
                : url.getParameter(SHARE_CONNECTIONS_KEY, (String) null);
            connections = Integer.parseInt(shareConnectionsStr);

            //创建公共ExchangeClient集合
            List<ReferenceCountExchangeClient> shareClients = getSharedClient(url, connections);
            //整理要返回的ExchangeClient集合
            ExchangeClient[] clients = new ExchangeClient[connections];
            Arrays.setAll(clients, shareClients::get);
            return clients;
        }

        //整理要返回的ExchangeClient集合
        ExchangeClient[] clients = new ExchangeClient[connections];
        for (int i = 0; i < clients.length; i++) {
            //不使用公共连接的情况下,会创建单独的ExchangeClient实例
            clients[i] = initClient(url);
        }
        return clients;
    }

    private List<ReferenceCountExchangeClient> getSharedClient(URL url, int connectNum) {
        //获取对端的地址(host:port)
        String key = url.getAddress();
        //从referenceClientMap集合中,获取与该地址连接的ReferenceCountExchangeClient集合
        Object clients = referenceClientMap.get(key);
        if (clients instanceof List) {
            List<ReferenceCountExchangeClient> typedClients = (List<ReferenceCountExchangeClient>) clients;
            //检测上述客户端集合是否全部可用
            if (checkClientCanUse(typedClients)) {
                //客户端全部可用时
                batchClientRefIncr(typedClients);
                return typedClients;
            }
        }

        List<ReferenceCountExchangeClient> typedClients = null;
        synchronized (referenceClientMap) {
            for (; ;) {
                //guarantee just one thread in loading condition. 
                //And Other is waiting It had finished.
                clients = referenceClientMap.get(key);
                if (clients instanceof List) {
                    typedClients = (List<ReferenceCountExchangeClient>) clients;
                    //double check,再次检测客户端是否可用
                    if (checkClientCanUse(typedClients)) {
                        batchClientRefIncr(typedClients);
                        return typedClients;
                    } else {
                        referenceClientMap.put(key, PENDING_OBJECT);
                        break;
                    }
                } else if (clients == PENDING_OBJECT) {
                    try {
                        referenceClientMap.wait();
                    } catch (InterruptedException ignored) {
                    }
                } else {
                    referenceClientMap.put(key, PENDING_OBJECT);
                    break;
                }
            }
        }

        try {
            //connectNum must be greater than or equal to 1
            //至少一个共享连接
            connectNum = Math.max(connectNum, 1);
            //If the clients is empty, then the first initialization is
            if (CollectionUtils.isEmpty(typedClients)) {
                //如果当前Clients集合为空,则直接通过initClient()方法初始化所有共享客户端
                typedClients = buildReferenceCountExchangeClientList(url, connectNum);
            } else {
                //如果只有部分共享客户端不可用,则只需要处理这些不可用的客户端
                for (int i = 0; i < typedClients.size(); i++) {
                    ReferenceCountExchangeClient referenceCountExchangeClient = typedClients.get(i);
                    //If there is a client in the list that is no longer available, create a new one to replace him.
                    if (referenceCountExchangeClient == null || referenceCountExchangeClient.isClosed()) {
                        typedClients.set(i, buildReferenceCountExchangeClient(url));
                        continue;
                    }
                    //增加引用
                    referenceCountExchangeClient.incrementAndGetCount();
                }
            }
        } finally {
            synchronized (referenceClientMap) {
                if (typedClients == null) {
                    referenceClientMap.remove(key);
                } else {
                    referenceClientMap.put(key, typedClients);
                }
                referenceClientMap.notifyAll();
            }
        }
        return typedClients;
    }

    private List<ReferenceCountExchangeClient> buildReferenceCountExchangeClientList(URL url, int connectNum) {
        List<ReferenceCountExchangeClient> clients = new ArrayList<>();
        for (int i = 0; i < connectNum; i++) {
            clients.add(buildReferenceCountExchangeClient(url));
        }
        return clients;
    }

    private ReferenceCountExchangeClient buildReferenceCountExchangeClient(URL url) {
        ExchangeClient exchangeClient = initClient(url);
        ReferenceCountExchangeClient client = new ReferenceCountExchangeClient(exchangeClient, DubboCodec.NAME);
        //read configs
        int shutdownTimeout = ConfigurationUtils.getServerShutdownTimeout(url.getScopeModel());
        client.setShutdownWaitTime(shutdownTimeout);
        return client;
    }

    private ExchangeClient initClient(URL url) {
        //获取客户端类型,并检查
        String str = url.getParameter(CLIENT_KEY, url.getParameter(SERVER_KEY, DEFAULT_REMOTING_CLIENT));
        if (StringUtils.isNotEmpty(str) && !url.getOrDefaultFrameworkModel().getExtensionLoader(Transporter.class).hasExtension(str)) {
            throw new RpcException("Unsupported client type: " + str + "," +
                " supported client type is " + StringUtils.join(url.getOrDefaultFrameworkModel().getExtensionLoader(Transporter.class).getSupportedExtensions(), " "));
        }
        try {
            url = new ServiceConfigURL(DubboCodec.NAME, url.getUsername(), url.getPassword(), url.getHost(), url.getPort(), url.getPath(), url.getAllParameters());
            //设置Codec2的扩展名
            url = url.addParameter(CODEC_KEY, DubboCodec.NAME);
            //设置默认的心跳间隔
            url = url.addParameterIfAbsent(HEARTBEAT_KEY, String.valueOf(DEFAULT_HEARTBEAT));
            //如果配置了延迟创建连接的特性,则创建LazyConnectExchangeClient
            //否则,调用Exchangers的connect()方法建立网络连接
            return url.getParameter(LAZY_CONNECT_KEY, false)
                ? new LazyConnectExchangeClient(url, requestHandler)
                : Exchangers.connect(url, requestHandler);
        } catch (RemotingException e) {
            throw new RpcException("Fail to create remoting client for service(" + url + "): " + e.getMessage(), e);
        }
    }
    ...
}

public class Exchangers {
    ...
    public static ExchangeClient connect(URL url, ExchangeHandler handler) throws RemotingException {
        ...
        //下面会调用到HeaderExchanger.connect()方法
        //传入的handler是DubboProtocol的requestHandler
        return getExchanger(url).connect(url, handler);
    }

    public static Exchanger getExchanger(URL url) {
        String type = url.getParameter(Constants.EXCHANGER_KEY, Constants.DEFAULT_EXCHANGER);
        //根据SPI机制,通过model组件体系去拿到对应的SPI扩展实现类实例
        //比如获取到的是一个HeaderExchanger
        return url.getOrDefaultFrameworkModel().getExtensionLoader(Exchanger.class).getExtension(type);
    }
    ...
}

public class HeaderExchanger implements Exchanger {
    public static final String NAME = "header";

    //NettyClient -> MultiMessageHandler -> HeartbeatHandler -> AllChannelHandler -> DecodeHandler -> HeaderExchangeHandler -> requestHandler
    //HeaderExchangeClient -> NettyClient
    @Override
    public ExchangeClient connect(URL url, ExchangeHandler handler) throws RemotingException {
        //传入的handler是DubboProtocol的requestHandler
        return new HeaderExchangeClient(Transporters.connect(url, new DecodeHandler(new HeaderExchangeHandler(handler))), true);
    }
    ...
}

public class Transporters {
    ...
    public static Client connect(URL url, ChannelHandler... handlers) throws RemotingException {
        ...
        //下面会调用NettyTransporter.connect()方法
        //传入的handler为装饰了DubboProtocol的requestHandler
        //返回一个NettyClient
        return getTransporter(url).connect(url, handler);
    }

    public static Transporter getTransporter(URL url) {
        //下面使用了getAdaptiveExtension()的自适应机制,针对接口动态生成代码然后创建代理类
        //代理类的方法,会根据url的参数动态提取对应的实现类的name名称,以及获取真正的需要使用的实现类
        //有了真正的实现类后,就可以去调用实现类的extension实例的方法了
        //比如下面会获取到一个NettyTransporter实例
        return url.getOrDefaultFrameworkModel().getExtensionLoader(Transporter.class).getAdaptiveExtension();
    }
    ...
}

public class NettyTransporter implements Transporter {
    ...
    public Client connect(URL url, ChannelHandler handler) throws RemotingException {
        //传入的handler为装饰了DubboProtocol的requestHandler
        //返回一个NettyClient
        return new NettyClient(url, handler);
    }
    ...
}

public abstract class AbstractClient extends AbstractEndpoint implements Client {
    ...
    public AbstractClient(URL url, ChannelHandler handler) throws RemotingException {
        //调用父类的构造方法
        super(url, handler);
        //解析URL,初始化executor
        initExecutor(url);
        //初始化底层的NIO库的相关组件
        doOpen();
        //connect. 创建底层连接
        connect();
        ...
    }

    protected void connect() throws RemotingException {
        ...
        doConnect();
        ...
    }
    ...
}

public class NettyClient extends AbstractClient {
    ...
    public NettyClient(final URL url, final ChannelHandler handler) throws RemotingException {
        super(url, wrapChannelHandler(url, handler));
    }

    protected void doOpen() throws Throwable {
        //创建NettyClientHandler,handler一般来说是用来处理网络请求的
        final NettyClientHandler nettyClientHandler = createNettyClientHandler();
        //创建Bootstrap,对于NettyClient必须构建一个Bootstrap
        bootstrap = new Bootstrap();
        initBootstrap(nettyClientHandler);
    }

    protected void doConnect() throws Throwable {
        long start = System.currentTimeMillis();
        //bootstrap.connect会对server端发起一个网络连接
        //但这个网络连接,并不是立刻就可以做好的
        ChannelFuture future = bootstrap.connect(getConnectAddress());
        ...
        boolean ret = future.awaitUninterruptibly(getConnectTimeout(), MILLISECONDS);
        ...
        //如果连接成功,此时就可以通过future拿到一个Channel
        //这个Channel代表着Client端和Server端Provider服务实例建立好的网络连接
        Channel newChannel = future.channel();
        ...
    }
    ...
}

相关推荐
麦兜*8 分钟前
Spring Boot 与 Ollama 集成部署私有LLM服务 的完整避坑指南,涵盖 环境配置、模型管理、性能优化 和 安全加固
java·spring boot·后端·安全·spring cloud·性能优化
树獭叔叔10 分钟前
详解 Python 的异步上下文管理器语法
后端·python
coding随想17 分钟前
深入浅出数据库语言SQL常用方法
后端
PetterHillWater28 分钟前
百度Comate的AI编程工具小试
后端·aigc
ezl1fe33 分钟前
RAG 每日一技(十三):检索一次不够?学习查询改写与迭代式检索!
人工智能·后端
自由的疯39 分钟前
Java 17 新特性之 instanceof 运算符
java·后端·架构
Cache技术分享39 分钟前
152. Java Lambda 表达式 - 深入理解 Java 的 Predicate 接口及其高效用法
前端·后端
卓伊凡40 分钟前
MongoDB 从3.4.0升级到4.0.0完整指南实战-优雅草蜻蜓I即时通讯水银版成功升级-卓伊凡|bigniu
数据库·后端
艾迪的技术之路42 分钟前
Superset安装步骤
后端·面试·github
自由的疯42 分钟前
Java 17 新特性之 Switch 表达式改进
java·后端·架构