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的分层架构原理

6.LoadBalance的负载均衡机制

处理负载均衡的入口是AbstractClusterInvoker的initLoadBalance()方法。

arduino 复制代码
//-> InvokerInvocationHandler.invoke()
//-> InvocationUtil.invoke()
//-> 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.initLoadBalance()

具体如下:

scss 复制代码
//-> AbstractClusterInvoker.invoke()
//-> AbstractClusterInvoker.initLoadBalance()
//-> FailoverClusterInvoker.doInvoke()
//-> AbstractClusterInvoker.select()
//-> AbstractClusterInvoker.doSelect()
//-> AbstractLoadBalance.select()
//-> RandomLoadBalance.doSelect()

//如果要对一个目标服务实例进行RPC调用,那么负责调用的这个组件就可以叫做Invoker
public abstract class AbstractClusterInvoker<T> implements ClusterInvoker<T> {
    ...
    public Result invoke(final Invocation invocation) throws RpcException {
        //检测当前Invoker是否已销毁
        checkWhetherDestroyed();
        InvocationProfilerUtils.enterDetailProfiler(invocation, () -> "Router route.");

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

        //通过SPI加载LoadBalance实例,也就是在这里选择出对应的负载均衡策略
        //比如下面默认会获取到一个RandomLoadBalance
        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);
        }
    }

    //Init LoadBalance.
    //if invokers is not empty, init from the first invoke's url and invocation
    //if invokes is empty, init a default LoadBalance(RandomLoadBalance)
    protected LoadBalance initLoadBalance(List<Invoker<T>> invokers, Invocation invocation) {
        ApplicationModel applicationModel = ScopeModelUtil.getApplicationModel(invocation.getModuleModel());
        if (CollectionUtils.isNotEmpty(invokers)) {
            //通过SPI获取负载均衡组件
            return applicationModel.getExtensionLoader(LoadBalance.class).getExtension(
                invokers.get(0).getUrl().getMethodParameter(
                    RpcUtils.getMethodName(invocation), LOADBALANCE_KEY, DEFAULT_LOADBALANCE
                )
            );
        } else {
            return applicationModel.getExtensionLoader(LoadBalance.class).getExtension(DEFAULT_LOADBALANCE);
        }
    }
    ...
}

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);
        //retry loop.
        RpcException le = null;//last exception.
        //构建了一个跟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++) {
            //Reselect before retry to avoid a change of candidate `invokers`.
            //NOTE: if `invokers` changed, then `invoked` also lose accuracy.
            //到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("...");
    }
    ...
}

public abstract class AbstractClusterInvoker<T> implements ClusterInvoker<T> {
    ...
    //第一个参数是此次使用的LoadBalance实现
    //第二个参数Invocation是此次服务调用的上下文信息
    //第三个参数是待选择的Invoker集合
    //第四个参数用来记录负载均衡已经选出来、尝试过的Invoker集合
    protected Invoker<T> select(LoadBalance loadbalance, Invocation invocation, List<Invoker<T>> invokers, List<Invoker<T>> selected) throws RpcException {
        //invokers不能为空,为空的话就直接返回
        if (CollectionUtils.isEmpty(invokers)) {
            return null;
        }

        //获取调用方法名,调用的方法名称处理逻辑是:
        //如果RPC调用是null,则method方法名就是一个空字符串,否则就是RPC调用里的方法名称
        String methodName = invocation == null ? StringUtils.EMPTY_STRING : invocation.getMethodName();

        //下面会获取sticky的配置,其中sticky表示粘滞连接
        //所谓粘滞连接是指Consumer会尽可能的调用同一个Provider节点,除非这个Provider无法提供服务
        //invokers代表了服务集群地址,首先会根据invokers获取第一个invoker
        //然后拿到这个invoker的URL,接着去获取URL中对应的sticky,其默认值是false
        boolean sticky = invokers.get(0).getUrl().getMethodParameter(methodName, CLUSTER_STICKY_KEY, DEFAULT_CLUSTER_STICKY);

        //ignore overloaded method
        //检测invokers列表是否包含stickyInvoker
        //如果不包含则说明stickyInvoker代表的服务提供者挂了,此时需要将其置空
        if (stickyInvoker != null && !invokers.contains(stickyInvoker)) {
            stickyInvoker = null;
        }

        //ignore concurrency problem
        //如果开启了粘滞连接特性,则需要先判断这个Provider节点是否已经重试过了
        //下面的判断前半部分表示粘滞连接,后半部分表示stickyInvoker未重试过
        if (sticky && stickyInvoker != null && (selected == null || !selected.contains(stickyInvoker))) {
            //检测当前stickyInvoker是否可用,如果可用,直接返回stickyInvoker
            if (availableCheck && stickyInvoker.isAvailable()) {
                return stickyInvoker;
            }
        }

        //执行到这里,说明前面的stickyInvoker为空,或者不可用
        //这里会继续调用doSelect选择新的Invoker对象
        //也就是基于LoadBalance去进行负载均衡选择一个Invoker出来
        Invoker<T> invoker = doSelect(loadbalance, invocation, invokers, selected);

        //是否开启粘滞,更新stickyInvoker为选择出来的invoker
        //sticky表示粘滞连接(粘滞调用)
        //所谓粘滞连接(粘滞调用)是指Consumer会尽可能的调用同一个Provider节点,除非这个Provider无法提供服务
        //也就是把一个Consumer端和一个Provider端粘在一起
        if (sticky) {
            stickyInvoker = invoker;
        }
        return invoker;
    }

    private Invoker<T> doSelect(LoadBalance loadbalance, Invocation invocation, List<Invoker<T>> invokers, List<Invoker<T>> selected) throws RpcException {
        //判断是否需要进行负载均衡,Invoker集合为空,直接返回null
        if (CollectionUtils.isEmpty(invokers)) {
            return null;
        }

        //只有一个Invoker对象,直接返回即可
        //如果invokers的数量就1个,那么目标Provider服务实例就一个
        //所以直接返回invokers里的第一个即可
        if (invokers.size() == 1) {
            Invoker<T> tInvoker = invokers.get(0);
            checkShouldInvalidateInvoker(tInvoker);
            return tInvoker;
        }

        //通过LoadBalance实现选择Invoker对象
        //即基于负载均衡的策略和算法选择出一个Invoker
        Invoker<T> invoker = loadbalance.select(invokers, getUrl(), invocation);

        //Invoke是否已经尝试调用过但是失败了
        boolean isSelected = selected != null && selected.contains(invoker);

        //Invoker是否不可用
        boolean isUnavailable = availableCheck && !invoker.isAvailable() && getUrl() != null;
        if (isUnavailable) {
            invalidateInvoker(invoker);
        }

        //如果LoadBalance选出的Invoker对象,已经尝试请求过了或不可用,则需要调用reselect()方法进行重选
        if (isSelected || isUnavailable) {
            try {
                //调用reselect()方法重选
                Invoker<T> rInvoker = reselect(loadbalance, invocation, invokers, selected, availableCheck);
                if (rInvoker != null) {
                    //如果重选的Invoker对象不为空,则直接返回这个rInvoker
                    invoker = rInvoker;
                } else {
                    //Check the index of current selected invoker, if it's not the last one, choose the one at index+1.
                    //如果选来选去都是空,那么对当前Invoker就直接选择它的下一个invoker即可
                    int index = invokers.indexOf(invoker);
                    try {
                        //Avoid collision
                        //如果重选的Invoker对象为空,则返回该Invoker的下一个Invoker对象
                        invoker = invokers.get((index + 1) % invokers.size());
                    } catch (Exception e) {
                        logger.warn(e.getMessage() + " may because invokers list dynamic change, ignore.", e);
                    }
                }
            } catch (Throwable t) {
                logger.error("cluster reselect fail reason is :" + t.getMessage() + " if can not solve, you can set cluster.availablecheck=false in url", t);
            }
        }
        return invoker;
    }
    ...
}

public abstract class AbstractLoadBalance implements LoadBalance {
    ...
    @Override
    public <T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) {
        if (CollectionUtils.isEmpty(invokers)) {
            //Invoker集合为空,直接返回null
            return null;
        }

        //Invoker集合只包含一个Invoker,则直接返回该Invoker对象
        if (invokers.size() == 1) {
            return invokers.get(0);
        }

        //Invoker集合包含多个Invoker对象时,交给doSelect()方法处理
        //交给doSelect()方法是个抽象方法,留给子类具体实现
        return doSelect(invokers, url, invocation);
    }

    protected abstract <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation);
    ...
}

public class RandomLoadBalance extends AbstractLoadBalance {
    public static final String NAME = "random";

    //Select one invoker between a list using a random criteria
    @Override
    protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
        //先拿到目标服务实例集群的invokers数量
        int length = invokers.size();
        if (!needWeightLoadBalance(invokers, invocation)) {
            //基于一个随机的类,通过其nextInt()方法拿到invokers数量范围之内的机器对应的invoker
            return invokers.get(ThreadLocalRandom.current().nextInt(length));
        }

        //什么是权重?
        //对于权重越高的invoker它被调用的几率会越高一些
        //而这里随机负载均衡的invokers它们被调用到的机会/几率是相同的
        //Every invoker has the same weight?
        boolean sameWeight = true;

        //the maxWeight of every invokers, the minWeight = 0 or the maxWeight of the last invoker
        //计算每个Invoker对象对应的权重,并填充到weights[]数组中
        int[] weights = new int[length];

        //The sum of weights
        int totalWeight = 0;
        for (int i = 0; i < length; i++) {
            //计算每个Invoker的权重,以及总权重totalWeight
            int weight = getWeight(invokers.get(i), invocation);
            //Sum
            totalWeight += weight;
            //save for later use
            weights[i] = totalWeight;
            //检测每个Provider的权重是否相同
            if (sameWeight && totalWeight != weight * (i + 1)) {
                sameWeight = false;
            }
        }

        //各个Invoker权重值不相等时,计算随机数落在哪个区间上
        if (totalWeight > 0 && !sameWeight) {
            //If (not every invoker has the same weight & at least one invoker's weight>0), select randomly based on totalWeight.
            //随机获取一个[0, totalWeight) 区间内的数字
            int offset = ThreadLocalRandom.current().nextInt(totalWeight);
            //Return a invoker based on the random value.
            for (int i = 0; i < length; i++) {
                if (offset < weights[i]) {
                    return invokers.get(i);
                }
            }
        }

        //If all invokers have the same weight value or totalWeight=0, return evenly.
        //各个Invoker权重值相同时,随机返回一个Invoker即可
        return invokers.get(ThreadLocalRandom.current().nextInt(length));
    }

    private <T> boolean needWeightLoadBalance(List<Invoker<T>> invokers, Invocation invocation) {
        Invoker invoker = invokers.get(0);
        URL invokerUrl = invoker.getUrl();
        if (invoker instanceof ClusterInvoker) {
            invokerUrl = ((ClusterInvoker<?>) invoker).getRegistryUrl();
        }

        // Multiple registry scenario, load balance among multiple registries.
        if (REGISTRY_SERVICE_REFERENCE_PATH.equals(invokerUrl.getServiceInterface())) {
            String weight = invokerUrl.getParameter(WEIGHT_KEY);
            if (StringUtils.isNotEmpty(weight)) {
                return true;
            }
        } else {
            String weight = invokerUrl.getMethodParameter(invocation.getMethodName(), WEIGHT_KEY);
            if (StringUtils.isNotEmpty(weight)) {
                return true;
            } else {
                String timeStamp = invoker.getUrl().getParameter(TIMESTAMP_KEY);
                if (StringUtils.isNotEmpty(timeStamp)) {
                    return true;
                }
            }
        }
        return false;
    }
    ...
}

通过负载均衡机制选出一个Invoker之后,就可以在FailoverClusterInvoker的doInvoke()方法中,通过FailoverClusterInvoker父类AbstractClusterInvoker的invokeWithContext()方法去执行Invoker的invoke()方法进行RPC调用。

java 复制代码
//-> FailoverClusterInvoker.doInvoke()
//-> AbstractClusterInvoker.invokeWithContext()
//-> ListenerInvokerWrapper.invoke()
//-> AbstractInvoker.invoke()

public class FailoverClusterInvoker<T> extends AbstractClusterInvoker<T> {
    ...
    //该方法会找一个Invoker,把invocation交给多个Invokers里的一个去发起RPC调用
    public Result doInvoke(Invocation invocation, final List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
        ...
        //1.下面会调用AbstractClusterInvoker的select()方法
        //select()方法会选择一个Invoker出来,具体逻辑是:
        //首先尝试用负载均衡算法去选
        //如果选出的Invoker是选过的或者不可用的,那么就直接reselect
        //也就是对选过的找一个可用的,对选不出的直接挑选下一个
        Invoker<T> invoker = select(loadbalance, invocation, copyInvokers, invoked);
        ...
        //2.调用AbstractClusterInvoker的invokeWithContext()方法
        //基于该Invoker发起RPC调用,并拿到一个result
        Result result = invokeWithContext(invoker, invocation);
        ...
    }
    ...
}

public abstract class AbstractClusterInvoker<T> implements ClusterInvoker<T> {
    ...
    protected Result invokeWithContext(Invoker<T> invoker, Invocation invocation) {
        setContext(invoker);
        Result result;
        try {
            if (ProfilerSwitch.isEnableSimpleProfiler()) {
                InvocationProfilerUtils.enterProfiler(invocation, "Invoker invoke. Target Address: " + invoker.getUrl().getAddress());
            }
            //下面会调用ListenerInvokerWrapper.invoke()方法
            result = invoker.invoke(invocation);
        } finally {
            clearContext(invoker);
            InvocationProfilerUtils.releaseSimpleProfiler(invocation);
        }
        return result;
    }
    ...
}

public class ListenerInvokerWrapper<T> implements Invoker<T> {
    //这是一个DubboInvoker
    private final Invoker<T> invoker;
    ...

    public Result invoke(Invocation invocation) throws RpcException {
        //下面会调用DubboInvoker的父类AbstractInvoker.invoke()方法
        return invoker.invoke(invocation);
    }
    ...
}

public abstract class AbstractInvoker<T> implements Invoker<T> {
    ...
    public Result invoke(Invocation inv) throws RpcException {
        ...
        //首先将传入的Invocation转换为RpcInvocation
        RpcInvocation invocation = (RpcInvocation) inv;
        //prepare rpc invocation
        prepareInvocation(invocation);
        //do invoke rpc invocation and return async result
        //RPC调用返回的结果是异步的:async
        AsyncRpcResult asyncResult = doInvokeAndReturn(invocation);
        //wait rpc result if sync
        //默认情况下发起的RPC请求是异步化操作
        //但如果需要同步的话,那么是可以在这里等待同步的结果
        waitForResultIfSync(asyncResult, invocation);
        return asyncResult;
    }

    private AsyncRpcResult doInvokeAndReturn(RpcInvocation invocation) {
        ...
        //调用子类实现的doInvoke()方法
        //比如DubboInvoker的doInvoke()方法
        asyncResult = (AsyncRpcResult) doInvoke(invocation);
        ...
    }

    protected abstract Result doInvoke(Invocation invocation) throws Throwable;
    ...
}

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

在AbstractInvoker的invoke()方法中,会通过调用AbstractInvoker的doInvokeAndReturn()方法来开始异步执行RPC调用。

arduino 复制代码
//-> InvokerInvocationHandler.invoke()
//-> InvocationUtil.invoke() [invoker.invoke(rpcInvocation).recreate()]
//...
//-> AbstractInvoker.invoke()
//-> AbstractInvoker.doInvokeAndReturn()
//-> DubboInvoker.doInvoke()
//-> AbstractInvoker.getCallbackExecutor()
//-> 配合线程池使用currentClient.request()发起RPC请求
//-> ReferenceCountExchangeClient.request()
//-> HeaderExchangeClient.request()
//-> HeaderExchangeChannel.request()
//-> DefaultFuture.newFuture()
//-> NettyClient.send() => AbstractPeer.send() => AbstractClient.send()
//-> NettyChannel.send() => channel.writeAndFlush()
scss 复制代码
public abstract class AbstractInvoker<T> implements Invoker<T> {
    ...
    public Result invoke(Invocation inv) throws RpcException {
        ...
        //首先将传入的Invocation转换为RpcInvocation
        RpcInvocation invocation = (RpcInvocation) inv;
        //prepare rpc invocation
        prepareInvocation(invocation);
        //do invoke rpc invocation and return async result,RPC调用返回的结果是异步的:async
        AsyncRpcResult asyncResult = doInvokeAndReturn(invocation);
        //wait rpc result if sync
        //默认情况下发起的RPC请求是异步化操作,但如果需要同步的话,那么是可以在这里等待同步的结果
        waitForResultIfSync(asyncResult, invocation);
        return asyncResult;
    }

    private AsyncRpcResult doInvokeAndReturn(RpcInvocation invocation) {
        ...
        //调用子类实现的doInvoke()方法
        //比如DubboInvoker的doInvoke()方法
        asyncResult = (AsyncRpcResult) doInvoke(invocation);
        ...
    }

    protected abstract Result doInvoke(Invocation invocation) throws Throwable;
   
    protected ExecutorService getCallbackExecutor(URL url, Invocation inv) {
        //首先通过SPI机制拿到ExecutorRepository------线程池存储组件
        //Dubbo会把内部所有的线程池都存放在该线程池存储组件里,或者要创建新的线程池也是通过它
        //model组件体系,其实就是封装了dubbo内部所有的公共的组件体系,可以用设计模式来形容
        //model组件设计思想就是门面模式,Model(本身是没有意义的) -> 门面,它封装了很多的组件如SPI、service数据、配置、Repository组件、BeanFactory
        //model就成为了一个门面,在整个dubbo框架里,如果要用到一些公共组件,就直接找model去获取就可以了
        if (InvokeMode.SYNC == RpcUtils.getInvokeMode(getUrl(), inv)) {
            return new ThreadlessExecutor();
        }
        return url.getOrDefaultApplicationModel()
            .getExtensionLoader(ExecutorRepository.class)
            .getDefaultExtension()
            .getExecutor(url);
    }
    ...
}

public class DubboInvoker<T> extends AbstractInvoker<T> {
    //ExchangeClient底层封装的就是NettyClient
    private final ExchangeClient[] clients;
    private final Set<Invoker<?>> invokers;
    ...

    public DubboInvoker(Class<T> serviceType, URL url, ExchangeClient[] clients, Set<Invoker<?>> invokers) {
        super(serviceType, url, new String[]{INTERFACE_KEY, GROUP_KEY, TOKEN_KEY});
        //DubboProtocol的protocolBindingRefer()方法在构建DubboInvoker时
        //会先通过DubboProtocol的getClients()方法获取ReferenceCountExchangeClient
        //然后再将这些ReferenceCountExchangeClient传入这里去构建DubboInvoker
        this.clients = clients;
        this.invokers = invokers;
        ...
    }

    protected Result doInvoke(final Invocation invocation) throws Throwable {
        RpcInvocation inv = (RpcInvocation) invocation;
        //此次调用的方法名称
        final String methodName = RpcUtils.getMethodName(invocation);
        //向Invocation中添加附加信息
        //这里将URL的path和version添加到附加信息中
        inv.setAttachment(PATH_KEY, getUrl().getPath());
        inv.setAttachment(VERSION_KEY, version);

        //ExchangeClient和Exchange都是跟网络相关的
        ExchangeClient currentClient;
        if (clients.length == 1) {
            //选择一个ExchangeClient实例
            currentClient = clients[0];
        } else {
            //如果有多个用于网络通信的Client,就会逐个去使用,这会是一个循环使用的过程
            currentClient = clients[index.getAndIncrement() % clients.length];
        }

        try {
            boolean isOneway = RpcUtils.isOneway(getUrl(), invocation);
            //根据调用的方法名称和配置计算此次调用的超时时间,默认是1秒
            int timeout = calculateTimeout(invocation, methodName);
            invocation.setAttachment(TIMEOUT_KEY, timeout);
            if (isOneway) {
                //不需要关注返回值的请求
                boolean isSent = getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false);
                currentClient.send(inv, isSent);
                return AsyncRpcResult.newDefaultAsyncResult(invocation);
            } else {
                //需要关注返回值的请求

                //1.获取处理响应的线程池
                //下面会调用AbstractInvoker的getCallbackExecutor()方法
                //对于同步请求,会使用ThreadlessExecutor
                //对于异步请求,则会使用共享的线程池
                ExecutorService executor = getCallbackExecutor(getUrl(), inv);

                //2.发起网络请求
                //currentClient.request()会使用上面选出的ExchangeClient执行request()方法将请求发送出去
                //下面其实会调用ReferenceCountExchangeClient的request()方法
                //thenApply()会将AppResponse封装成AsyncRpcResult返回
                CompletableFuture<AppResponse> appResponseFuture = 
                    currentClient.request(inv, timeout, executor).thenApply(obj -> (AppResponse) obj);

                //3.处理请求的响应结果
                //save for 2.6.x compatibility, for example, TraceFilter in Zipkin uses com.alibaba.xxx.FutureAdapter
                FutureContext.getContext().setCompatibleFuture(appResponseFuture);
                AsyncRpcResult result = new AsyncRpcResult(appResponseFuture, inv);
                result.setExecutor(executor);

                //要想拿到AppResponse结果,就需要基于CompletableFuture进行同步等待
                //只要Provider返回响应结果,就必然会写入到CompletableFuture里
                //此时就可以通过CompletableFuture取出AppResponse结果了
                //比如InvocationUtil的invoke()方法在执行"invoker.invoke(rpcInvocation).recreate()"时
                //就会调用AsyncRpcResult的recreate()方法来获取Provider返回的响应结果
                //也就是会调用到CompletableFuture的get()方法获取Provider返回的响应结果
                return result;
            }
        } catch (TimeoutException e) {
            ...
        }
    }
    ...
}

public class AsyncRpcResult implements Result {
    private CompletableFuture<AppResponse> responseFuture;
    private Invocation invocation;
    private final boolean async;
    private Executor executor;
    private RpcContext.RestoreContext storedContext;
    ...

    public AsyncRpcResult(CompletableFuture<AppResponse> future, Invocation invocation) {
        this.responseFuture = future;
        this.invocation = invocation;
        RpcInvocation rpcInvocation = (RpcInvocation) invocation;
        if ((rpcInvocation.get(PROVIDER_ASYNC_KEY) != null || InvokeMode.SYNC != rpcInvocation.getInvokeMode()) && !future.isDone()) {
            async = true;
            this.storedContext = RpcContext.clearAndStoreContext();
        } else {
            async = false;
        }
    }

    @Override
    public Object recreate() throws Throwable {
        RpcInvocation rpcInvocation = (RpcInvocation) invocation;
        //对InvokeMode模式进行判断
        if (InvokeMode.FUTURE == rpcInvocation.getInvokeMode()) {
            //如果模式为FUTURE,则表示支持异步化,所以返回的就是一个future对象
            //而这个future异步对象代表的就是一个异步化结果,此时可能有结果了也可能没有结果,这需要自己去获取
            return RpcContext.getClientAttachment().getFuture();
        } else if (InvokeMode.ASYNC == rpcInvocation.getInvokeMode()) {
            //如果模式是ASYNC,则创建默认结果返回
            return createDefaultValue(invocation).recreate();
        }
        //如果模式SYNC
        return getAppResponse().recreate();
    }

    public Result getAppResponse() {
        try {
            //DubboInvoker.doInvoke()方法返回的AsyncRpcResult会封装一个CompletableFuture进去
            //这里首先会做一个判断
            //如果CompletableFuture的isDone()方法返回true,则表示已经完成请求并拿到了响应
            //响应结果会通过HeaderExchangeHandler.received()被放到CompletableFuture里面
            if (responseFuture.isDone()) {//检测responseFuture是否已完成
                //从CompletableFuture进行阻塞式循环获取AppResponse并进行返回
                return responseFuture.get();
            }
        } catch (Exception e) {
            //This should not happen in normal request process;
            logger.error("Got exception when trying to fetch the underlying result from AsyncRpcResult.");
            throw new RpcException(e);
        }
        //根据调用方法的返回值,生成默认值
        return createDefaultValue(invocation);
    }
    
    @Override
    public Result get() throws InterruptedException, ExecutionException {
        if (executor != null && executor instanceof ThreadlessExecutor) {
            //针对ThreadlessExecutor的特殊处理,这里调用waitAndDrain()等待响应
            ThreadlessExecutor threadlessExecutor = (ThreadlessExecutor) executor;
            threadlessExecutor.waitAndDrain();
        }
        //非ThreadlessExecutor线程池的场景中
        //则直接调用Future(最底层是DefaultFuture)的get()方法阻塞
        return responseFuture.get();
    }

    @Override
    public Result get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
        if (executor != null && executor instanceof ThreadlessExecutor) {
            //针对ThreadlessExecutor的特殊处理,这里调用waitAndDrain()等待响应
            ThreadlessExecutor threadlessExecutor = (ThreadlessExecutor) executor;
            threadlessExecutor.waitAndDrain();
        }
        //非ThreadlessExecutor线程池的场景中
        //则直接调用Future(最底层是DefaultFuture)的get()方法阻塞
        return responseFuture.get(timeout, unit);
    }
    ...
}
java 复制代码
final class ReferenceCountExchangeClient implements ExchangeClient {
    private ExchangeClient client;
    ...

    //ReferenceCountExchangeClient的构入口是DubboProtocol的initClient()方法
    public ReferenceCountExchangeClient(ExchangeClient client, String codec) {
        this.client = client;
        this.referenceCount.incrementAndGet();
        this.url = client.getUrl();
    }

    public CompletableFuture<Object> request(Object request, int timeout, ExecutorService executor) throws RemotingException {
        //下面会调用HeaderExchangeClient.request()方法
        return client.request(request, timeout, executor);
    }
    ...
}

public class HeaderExchangeClient implements ExchangeClient {
    ...
    public CompletableFuture<Object> request(Object request, int timeout, ExecutorService executor) throws RemotingException {
        //下面会调用HeaderExchangeChannel.request()  
        return channel.request(request, timeout, executor);
    }
    ...
}

final class HeaderExchangeChannel implements ExchangeChannel {
    ...
    public CompletableFuture<Object> request(Object request, int timeout, ExecutorService executor) throws RemotingException {
        ...
        //为什么Dubbo中要设计出来Exchange这一层
        //官方的解释是Exchange这一层会负责同步转异步
        //也就是进行Request/Response网络请求响应模型的封装
        //当Consumer端最终发送请求时,最终会执行到这里

        //这里首先会构建一个Request,把RpcInvocation对象封装为Request对象
        //也就是把一个业务语义的对象RpcInvocation,封装为网络通信里的请求响应模型里的Request对象
        //因此从这一步开始,会进入网络通信的范围,引入Request这些概念,便是多年架构经验设计出来的
        //如果直接将RpcInvocation交给Netty框架去进行处理,那么就不太符合网络通信的请求响应模型了

        //然后会创建future,并调用channel.send()进行请求发送,而这又涉及了同步转异步的过程
        //也就是最后会直接返回一个future,如果需要同步等待响应,那么可以调用future.get()方法进行阻塞

        //create request.
        Request req = new Request();
        req.setVersion(Version.getProtocolVersion());
        //双向请求,表示请求过去了还得返回对应的响应
        req.setTwoWay(true);
        //这个request就是我们的RpcInvocation
        req.setData(request);

        //创建完一个future后,调用方后续在收到响应结果时会再来进行处理
        //所以返回的异步future结果,与发送请求是脱离开来的
        //下面会将NettyClient、request、timeout、线程池executor,封装成一个future
        DefaultFuture future = DefaultFuture.newFuture(channel, req, timeout, executor);

        //正常情况下,一般不会有超时问题
        try {
            //下面会调用NettyClient的send()方法
            //也就是调用AbstractPeer.send()方法,因为NettyClient没有覆盖其父类的send()方法
            //AbstractClient.send()又会调用NettyChannel.send()方法
            //NettyChannel.send()又会调用Netty底层的channel的writeAndFlush()方法
            //会同步发起请求,但默认不会等待请求完成了才返回
            channel.send(req);
        } catch (RemotingException e) {
            future.cancel();
            throw e;
        }
        return future;
    }
    ...
}

public class DefaultFuture extends CompletableFuture<Object> {
    private final Channel channel;
    private final Request request;
    private final Long id;
    private final int timeout;
    //请求ID和DefaultFuture的映射关系
    private static final Map<Long, DefaultFuture> FUTURES = new ConcurrentHashMap<>();
    //请求ID和Channel的映射关系
    private static final Map<Long, Channel> CHANNELS = new ConcurrentHashMap<>();

    private static final GlobalResourceInitializer<Timer> TIME_OUT_TIMER = 
        new GlobalResourceInitializer<>(
            () -> new HashedWheelTimer(new NamedThreadFactory("dubbo-future-timeout", true), 30, TimeUnit.MILLISECONDS), 
            DefaultFuture::destroy
        );
    ...

    private DefaultFuture(Channel channel, Request request, int timeout) {
        this.channel = channel;
        this.request = request;
        this.id = request.getId();
        this.timeout = timeout > 0 ? timeout : channel.getUrl().getPositiveParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT);
        //put into waiting map.
        FUTURES.put(id, this);
        CHANNELS.put(id, channel);
    }

    public static DefaultFuture newFuture(Channel channel, Request request, int timeout, ExecutorService executor) {
        //1.根据channel、request、timeout创建DefaultFuture对象
        //然后设置其线程池为executor,该过程只是简单的赋值操作
        final DefaultFuture future = new DefaultFuture(channel, request, timeout);
        future.setExecutor(executor);
        //ThreadlessExecutor needs to hold the waiting future in case of circuit return.
        if (executor instanceof ThreadlessExecutor) {
            ((ThreadlessExecutor) executor).setWaitingFuture(future);
        }
        //2.timeout check
        timeoutCheck(future);
        return future;
    }

    //利用TIME_OUT_TIMER时间轮启动一个定时任务进行task超时检查
    private static void timeoutCheck(DefaultFuture future) {
        TimeoutCheckTask task = new TimeoutCheckTask(future.getId());
        future.timeoutCheckTask = TIME_OUT_TIMER.get().newTimeout(task, future.getTimeout(), TimeUnit.MILLISECONDS);
    }
    ...
}

public class NettyClient extends AbstractClient {
    ...
    ...
}

public abstract class AbstractPeer implements Endpoint, ChannelHandler {
    ...
    public void send(Object message) throws RemotingException {
        //false表示不会同步等待发送完毕后才返回
        //从入参为false可知,NettyChannel发送数据时,默认就是异步化的
        //比如下面会调用AbstractClient.send()
        send(message, url.getParameter(Constants.SENT_KEY, false));
    }
    ...
}

public abstract class AbstractClient extends AbstractEndpoint implements Client {
    private final Lock connectLock = new ReentrantLock();
    private final boolean needReconnect;
    protected volatile ExecutorService executor;
    ...

    public AbstractClient(URL url, ChannelHandler handler) throws RemotingException {
        //调用父类的构造方法
        super(url, handler);
        //解析URL,初始化needReconnect值
        needReconnect = url.getParameter(Constants.SEND_RECONNECT_KEY, true);
        //解析URL,初始化executor线程池
        initExecutor(url);

        try {
            //初始化底层的NIO库的相关组件
            doOpen();
        } catch (Throwable t) {
            close();
            throw new RemotingException("...");
        }

        try {
            //connect创建底层连接
            connect();
        } catch (Throwable t) {
            close();
            throw new RemotingException("...");
        }
    }

    private void initExecutor(URL url) {
        ExecutorRepository executorRepository = url.getOrDefaultApplicationModel()
            .getExtensionLoader(ExecutorRepository.class).getDefaultExtension();
        url = url.addParameter(THREAD_NAME_KEY, CLIENT_THREAD_POOL_NAME)
            .addParameterIfAbsent(THREADPOOL_KEY, DEFAULT_CLIENT_THREADPOOL);
        executor = executorRepository.createExecutorIfAbsent(url);
    }

    @Override
    public void send(Object message, boolean sent) throws RemotingException {
        if (needReconnect && !isConnected()) {
            connect();
        }
        //比如下面会获取到NettyChannel
        Channel channel = getChannel();
        if (channel == null || !channel.isConnected()) {
            throw new RemotingException(this, "message can not send, because channel is closed . url:" + getUrl());
        }
        //比如下面会调用NettyChannel.send()
        //因为NettyClient的doConnect()方法建立连接时会拿到一个Channel
        //然后将这个Channel赋值到NettyClient的channel属性中
        channel.send(message, sent);
    }

    protected void connect() throws RemotingException {
        connectLock.lock();
        try {
            doConnect();
        } finally {
            connectLock.unlock();
        }
    }
    ...
}

final class NettyChannel extends AbstractChannel {
    ...
    public void send(Object message, boolean sent) throws RemotingException {
        ...
        //下面这行代码的channel是一个NioSocketChannel
        ChannelFuture future = channel.writeAndFlush(message);
        if (sent) {
            //wait timeout ms
            timeout = getUrl().getPositiveParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT);
            success = future.await(timeout);
        }
        ...
    }
    ...
}

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

AbstractInvoker的waitForResultIfSync()方法是等待响应的入口。

java 复制代码
//-> 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.initLoadBalance()
//-> FailoverClusterInvoker.doInvoke()
//-> AbstractClusterInvoker.select()
//-> AbstractClusterInvoker.doSelect()
//-> AbstractLoadBalance.select()
//-> RandomLoadBalance.doSelect()
//-> AbstractClusterInvoker.invokeWithContext()
//-> ListenerInvokerWrapper.invoke()
//-> AbstractInvoker.invoke()
//-> AbstractInvoker.doInvokeAndReturn()
//-> DubboInvoker.doInvoke()
//-> AbstractInvoker.waitForResultIfSync()
//-> AsyncRpcResult.get()

public abstract class AbstractInvoker<T> implements Invoker<T> {
    ...
    public Result invoke(Invocation inv) throws RpcException {
        ...
        //首先将传入的Invocation转换为RpcInvocation
        RpcInvocation invocation = (RpcInvocation) inv;
        //prepare rpc invocation
        prepareInvocation(invocation);
        //do invoke rpc invocation and return async result,RPC调用返回的结果是异步的:async
        AsyncRpcResult asyncResult = doInvokeAndReturn(invocation);
        //wait rpc result if sync
        //默认情况下发起的RPC请求是异步化操作,但如果需要同步的话,那么是可以在这里等待同步的结果
        waitForResultIfSync(asyncResult, invocation);
        return asyncResult;
    }

    private AsyncRpcResult doInvokeAndReturn(RpcInvocation invocation) {
        ...
        //调用子类实现的doInvoke()方法
        //比如DubboInvoker的doInvoke()方法
        asyncResult = (AsyncRpcResult) doInvoke(invocation);
        ...
    }

    private void waitForResultIfSync(AsyncRpcResult asyncResult, RpcInvocation invocation) {
        ...
        Object timeout = invocation.getObjectAttachmentWithoutConvert(TIMEOUT_KEY);
        if (timeout instanceof Integer) {
            asyncResult.get((Integer) timeout, TimeUnit.MILLISECONDS);
        } else {
            asyncResult.get(Integer.MAX_VALUE, TimeUnit.MILLISECONDS);
        }
        ...
    }
    ...
}

public class AsyncRpcResult implements Result {
    private CompletableFuture<AppResponse> responseFuture;
    ...

    public Result get() throws InterruptedException, ExecutionException {
        if (executor != null && executor instanceof ThreadlessExecutor) {
            //针对ThreadlessExecutor的特殊处理,这里调用waitAndDrain()等待响应
            ThreadlessExecutor threadlessExecutor = (ThreadlessExecutor) executor;
            threadlessExecutor.waitAndDrain();
        }
        //非ThreadlessExecutor线程池的场景中,则直接调用Future(最底层是DefaultFuture)的get()方法阻塞
        return responseFuture.get();
    }
    ...
}

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

Consumer端发送过来的RPC请求,会由Provider端的NettyServer进行处理。

bash 复制代码
//-> NettyServer
//-> NettyServerHandler.channelRead()
//-> NettyChannel.getOrAddChannel() [读取请求,获取到NettyChannel]
//-> AbstractPeer.received()
//-> MultiMessageHandler.received()
//-> HeartbeatHandler.received()
//-> AllChannelHandler.received()
//-> WrappedChannelHandler.getPreferredExecutorService() [获取线程池]
//-> new ChannelEventRunnable()
//-> AllChannelHandler.received()#executor.execute() [提交一个异步任务给线程池进行处理]
//-> ChannelEventRunnable.run() [启动任务处理请求]
//-> DecodeHandler.received()
//-> HeaderExchangeHandler.received()
//-> HeaderExchangeHandler.handleRequest() [对请求进行处理]
//-> DubboProtocol.requestHandler.reply()
//-> FilterChainBuilder.FilterChainNode.invoke()
//-> AbstractProxyInvoker.invoke() [在FilterChain中最终会跑到AbstractProxyInvoker.invke()]
//-> JavassistProxyFactory.getInvoker().doInvoke()
//-> 目标实现类方法
java 复制代码
public class NettyServer extends AbstractServer {
    private EventLoopGroup bossGroup;
    private EventLoopGroup workerGroup;
    private Map<String, Channel> channels;
    private io.netty.channel.Channel channel;
    private final int serverShutdownTimeoutMills;

    //NettyServer在构建的过程中,会构建和打开真正的网络服务器
    //这里是基于netty4技术去实现了网络服务器构建和打开的,一旦打开后,Netty Server就开始监听指定的端口号
    //当发现有请求过来就可以去进行处理,也就是通过ProxyInvoker去调用本地实现类的目标方法
    //入参handler其实就是DubboProtocol中的requestHandler
    //入参handler会先被HeartbeatHandler装饰,再被MultiMessageHandler装饰,再被其他修饰等等
    public NettyServer(URL url, ChannelHandler handler) throws RemotingException {
        //you can customize name and type of client thread pool by THREAD_NAME_KEY and THREAD_POOL_KEY in CommonConstants.
        //the handler will be wrapped: MultiMessageHandler -> HeartbeatHandler -> handler
        super(ExecutorUtil.setThreadName(url, SERVER_THREAD_POOL_NAME), ChannelHandlers.wrap(handler, url));
        //read config before destroy
        serverShutdownTimeoutMills = ConfigurationUtils.getServerShutdownTimeout(getUrl().getOrDefaultModuleModel());
    }

    //Init and start netty server
    @Override
    protected void doOpen() throws Throwable {
        //创建ServerBootstrap
        bootstrap = new ServerBootstrap();

        //EventLoop,也可以理解为网络服务器,它会监听一个本地的端口号
        //外部系统针对本地服务器端口号发起连接、通信、网络事件时,监听的端口号就会不停的产生网络事件
        //EventLoop网络服务器,还会不停轮询监听到的网络事件
        //boss的意思是负责监听端口号是否有外部系统的连接请求,它是一个EventLoopGroup线程池
        //如果发现了网络事件,就需要进行请求处理,可以通过workerGroup里的多个线程进行并发处理
        //创建boss EventLoopGroup,线程数是1
        bossGroup = createBossGroup();

        //创建worker EventLoopGroup,线程数是CPU核数 + 1,但最多不会超过32个线程
        workerGroup = createWorkerGroup();

        //创建NettyServerHandler
        //它是一个Netty中的ChannelHandler实现,不是Dubbo Remoting层的ChannelHandler接口的实现
        final NettyServerHandler nettyServerHandler = createNettyServerHandler();

        //获取当前NettyServer创建的所有Channel
        //channels集合中的Channel不是Netty中的Channel对象,而是Dubbo Remoting层的Channel对象
        channels = nettyServerHandler.getChannels();

        //初始化ServerBootstrap,指定boss和worker EventLoopGroup
        initServerBootstrap(nettyServerHandler);

        //绑定指定的地址和端口
        ChannelFuture channelFuture = bootstrap.bind(getBindAddress());

        //等待bind操作完成
        channelFuture.syncUninterruptibly();
        channel = channelFuture.channel();
    }

    protected EventLoopGroup createBossGroup() {
        return NettyEventLoopFactory.eventLoopGroup(1, EVENT_LOOP_BOSS_POOL_NAME);
    }

    protected EventLoopGroup createWorkerGroup() {
        return NettyEventLoopFactory.eventLoopGroup(
            getUrl().getPositiveParameter(IO_THREADS_KEY, Constants.DEFAULT_IO_THREADS),
            EVENT_LOOP_WORKER_POOL_NAME
        );
    }

    //NettyServer本身就是一个handler,它的顶级父类实现了ChannelHandler接口
    //这个方法会将NettyServer自己作为参数传入NettyServerHandler之中
    protected NettyServerHandler createNettyServerHandler() {
        return new NettyServerHandler(getUrl(), this);
    }

    protected void initServerBootstrap(NettyServerHandler nettyServerHandler) {
        boolean keepalive = getUrl().getParameter(KEEP_ALIVE_KEY, Boolean.FALSE);
        bootstrap.group(bossGroup, workerGroup)
        .channel(NettyEventLoopFactory.serverSocketChannelClass())
        .option(ChannelOption.SO_REUSEADDR, Boolean.TRUE)
        .childOption(ChannelOption.TCP_NODELAY, Boolean.TRUE)
        .childOption(ChannelOption.SO_KEEPALIVE, keepalive)
        .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
        .childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                //连接空闲超时时间
                int idleTimeout = UrlUtils.getIdleTimeout(getUrl());
                //NettyCodecAdapter中会创建Decoder和Encoder
                NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyServer.this);
                if (getUrl().getParameter(SSL_ENABLED_KEY, false)) {
                    ch.pipeline().addLast("negotiation", new SslServerTlsHandler(getUrl()));
                }
                ch.pipeline()
                    //注册Decoder和Encoder
                    .addLast("decoder", adapter.getDecoder())
                    .addLast("encoder", adapter.getEncoder())
                    //注册IdleStateHandler
                    .addLast("server-idle-handler", new IdleStateHandler(0, 0, idleTimeout, MILLISECONDS))
                    //注册NettyServerHandler
                    .addLast("handler", nettyServerHandler);
                }
        });
    }
}

public class ChannelHandlers {
    private static ChannelHandlers INSTANCE = new ChannelHandlers();

    protected ChannelHandlers() {
    }

    public static ChannelHandler wrap(ChannelHandler handler, URL url) {
        return ChannelHandlers.getInstance().wrapInternal(handler, url);
    }

    protected static ChannelHandlers getInstance() {
        return INSTANCE;
    }

    static void setTestingChannelHandlers(ChannelHandlers instance) {
        INSTANCE = instance;
    }

    //MultiMessageHandler -> HeartbeatHandler -> AllChannelHandler -> DecodeHandler -> HeaderExchangeHandler -> DubboProtocol的requestHandler
    //其中AllChannelHandler是由下面代码通过SPI获取到的自适应实现类AllDispatcher的dispatch()方法返回的
    protected ChannelHandler wrapInternal(ChannelHandler handler, URL url) {
        return new MultiMessageHandler(new HeartbeatHandler(url.getOrDefaultFrameworkModel().getExtensionLoader(Dispatcher.class)
            .getAdaptiveExtension().dispatch(handler, url)));
    }
}

public class NettyServerHandler extends ChannelDuplexHandler {
    private final URL url;
    private final ChannelHandler handler;
    ...

    //NettyServer会将自己作为参数传入NettyServerHandler的构造函数之中
    public NettyServerHandler(URL url, ChannelHandler handler) {
        if (url == null) {
            throw new IllegalArgumentException("url == null");
        }
        if (handler == null) {
            throw new IllegalArgumentException("handler == null");
        }
        this.url = url;
        this.handler = handler;
    }

    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        NettyChannel channel = NettyChannel.getOrAddChannel(ctx.channel(), url, handler);
        //下面会调用AbstractPeer.received()方法
        handler.received(channel, msg);
    }
    ...
}

public abstract class AbstractPeer implements Endpoint, ChannelHandler {
    ...
    public void received(Channel ch, Object msg) throws RemotingException {
        if (closed) {
            return;
        }
        //这里的handler会被如下handler先后装饰
        //MultiMessageHandler -> HeartbeatHandler -> AllChannelHandler -> DecodeHandler -> HeaderExchangeHandler -> DubboProtocol的requestHandler
        //下面会调用MultiMessageHandler.received()方法
        handler.received(ch, msg);
    }
    ...
}
scala 复制代码
public class MultiMessageHandler extends AbstractChannelHandlerDelegate {
    ...
    public void received(Channel channel, Object message) throws RemotingException {
        ...
        //下面会执行HeartbeatHandler.received()方法
        handler.received(channel, message);
    }
    ...
}

public class HeartbeatHandler extends AbstractChannelHandlerDelegate {
    ...
    public void received(Channel channel, Object message) throws RemotingException {
        //记录最近的读写事件时间戳
        setReadTimestamp(channel);

        if (isHeartbeatRequest(message)) {
            //收到心跳请求
            Request req = (Request) message;
            if (req.isTwoWay()) {
                //返回心跳响应,注意,携带请求的ID
                Response res = new Response(req.getId(), req.getVersion());
                res.setEvent(HEARTBEAT_EVENT);
                channel.send(res);
                ...
            }
            return;
        }
        ...
        //下面会执行AllChannelHandler.received()方法
        handler.received(channel, message);
    }
    ...
}

public class AllChannelHandler extends WrappedChannelHandler {
    ...
    @Override
    public void received(Channel channel, Object message) throws RemotingException {
        //通过父类WrappedChannelHandler的方法获取线程池
        ExecutorService executor = getPreferredExecutorService(message);
        try {
            //将消息封装成ChannelEventRunnable任务,提交到线程池中执行
            executor.execute(new ChannelEventRunnable(channel, handler, ChannelState.RECEIVED, message));
        } catch (Throwable t) {
            //如果线程池满了,请求会被拒绝,这里会根据请求配置决定是否返回一个说明性的响应
            if (message instanceof Request && t instanceof RejectedExecutionException){
                sendFeedback(channel, (Request) message, t);
                return;
            }
            throw new ExecutionException(message, channel, getClass() + " error when process received event .", t);
        }
    }
    ...
}

public class WrappedChannelHandler implements ChannelHandlerDelegate {
    ...
    public ExecutorService getPreferredExecutorService(Object msg) {
        if (msg instanceof Response) {
            Response response = (Response) msg;
            //获取请求关联的DefaultFuture
            DefaultFuture responseFuture = DefaultFuture.getFuture(response.getId());

            if (responseFuture == null) {
                return getSharedExecutorService();
            } else {
                //如果请求关联了线程池,则会获取相关的线程来处理响应
                ExecutorService executor = responseFuture.getExecutor();
                if (executor == null || executor.isShutdown()) {
                    executor = getSharedExecutorService();
                }
                return executor;
            }
        } else {
            //返回共享线程池
            return getSharedExecutorService();
        }
    }

    public ExecutorService getSharedExecutorService() {
        if (url.getApplicationModel() == null || url.getApplicationModel().isDestroyed()) {
            return GlobalResourcesRepository.getGlobalExecutorService();
        }
        ApplicationModel applicationModel = url.getOrDefaultApplicationModel();

        //ExecutorRepository主要是负责来获取线程池的,ExecutorRepository是一个存储线程池的组件
        //下面会通过ExtensionLoader,基于SPI扩展机制,去获取具体扩展实现类对象
        ExecutorRepository executorRepository = applicationModel.getExtensionLoader(ExecutorRepository.class).getDefaultExtension();
        //传入一个url,从url里提取一些参数出来,然后根据url参数来决定会获取到什么样的线程池
        ExecutorService executor = executorRepository.getExecutor(url);
        if (executor == null) {
            //创建和构建线程池
            executor = executorRepository.createExecutorIfAbsent(url);
        }
        return executor;
    }
    ...
}

public class ChannelEventRunnable implements Runnable {
    ...
    public void run() {
        ...
        //接收到了请求
        //比如会调用DecodeHandler.received()方法
        handler.received(channel, message);
        ...
    }
    ...
}

public class DecodeHandler extends AbstractChannelHandlerDelegate {
    public void received(Channel channel, Object message) throws RemotingException {
        if (message instanceof Decodeable) {
            decode(message);
        }
        if (message instanceof Request) {
            decode(((Request) message).getData());
        }
        if (message instanceof Response) {
            decode(((Response) message).getResult());
        }
        //比如会调用HeaderExchangeHandler.received()
        handler.received(channel, message);
    }
    ...
}

public class HeaderExchangeHandler implements ChannelHandlerDelegate {
    ...
    public void received(Channel channel, Object message) throws RemotingException {
        //收到Request请求
        if (message instanceof Request) {
        //handle request.
        Request request = (Request) message;
        if (request.isEvent()) {
            //事件类型的请求
            handlerEvent(channel, request);
        } else {
            //非事件的请求
            if (request.isTwoWay()) {//twoway
                //下面会对请求进行处理
                handleRequest(exchangeChannel, request);
            } else {//oneway
                handler.received(exchangeChannel, request.getData());
            }
        }
        ...
    }

    void handleRequest(final ExchangeChannel channel, Request req) throws RemotingException {
        Response res = new Response(req.getId(), req.getVersion());
        //请求解码失败
        if (req.isBroken()) {
            Object data = req.getData();
            String msg;
            if (data == null) {
                msg = null;
            } else if (data instanceof Throwable) {
                msg = StringUtils.toString((Throwable) data);
            } else {
                msg = data.toString();
            }
            res.setErrorMessage("Fail to decode request due to: " + msg);
            res.setStatus(Response.BAD_REQUEST);
            //将异常响应返回给对端
            channel.send(res);
            return;
        }

        //find handler by message class.
        Object msg = req.getData();
        try {
            //交给上层实现的ExchangeHandler进行请求处理,比如DubboProtocol的requestHandler
            CompletionStage<Object> future = handler.reply(channel, msg);
            future.whenComplete((appResult, t) -> {
                //处理结束后的回调
                try {
                    if (t == null) {//返回正常响应
                        res.setStatus(Response.OK);
                        res.setResult(appResult);
                    } else {//处理过程发生异常,设置异常信息和错误码
                        res.setStatus(Response.SERVICE_ERROR);
                        res.setErrorMessage(StringUtils.toString(t));
                    }
                    //发送响应
                    channel.send(res);
                } catch (RemotingException e) {
                    logger.warn("Send result to consumer failed, channel is " + channel + ", msg is " + e);
                }
            });
        } catch (Throwable e) {
            res.setStatus(Response.SERVICE_ERROR);
            res.setErrorMessage(StringUtils.toString(e));
            channel.send(res);
        }
    }
    ...
}

public class DubboProtocol extends AbstractProtocol {
    ...
    private final ExchangeHandler requestHandler = new ExchangeHandlerAdapter() {
        public CompletableFuture<Object> reply(ExchangeChannel channel, Object message) throws RemotingException {
            ...
            //将客户端发过来的message转换为Invocation对象
            Invocation inv = (Invocation) message;
            //获取此次调用Invoker对象
            Invoker<?> invoker = getInvoker(channel, inv);
            ...
            //Provider服务端会在下面执行真正的本地实现类的调用
            //比如下面会调用到FilterChainBuilder.FilterChainNode.invoke()方法
            Result result = invoker.invoke(inv);
            //返回结果
            return result.thenApply(Function.identity());
        }
        ...
    };
    ...
}

public interface FilterChainBuilder {
    class FilterChainNode<T, TYPE extends Invoker<T>, FILTER extends BaseFilter> implements Invoker<T> {
        ...
        public Result invoke(Invocation invocation) throws RpcException {
            ...
            //比如Consumer端处理时下面会调用ConsumerContextFilter的invoke()方法
            //Provider端处理时下面会最终调用AbstractProxyInvoker.invoke()方法
            asyncResult = filter.invoke(nextNode, invocation);
            ...
        }
    }
    ...
}

public abstract class AbstractProxyInvoker<T> implements Invoker<T> {
    ...
    //当Netty Server接受到了请求后,经过解析就会知道是要调用什么
    //然后会把解析出来的数据放入Invocation中
    //于是可以通过AbstractProxyInvoker的invoke()方法来进行调用
    @Override
    public Result invoke(Invocation invocation) throws RpcException {
        //执行doInvoke()方法,调用业务实现
        Object value = doInvoke(proxy, invocation.getMethodName(), invocation.getParameterTypes(), invocation.getArguments());
    }
    ...
}

public class JavassistProxyFactory extends AbstractProxyFactory {
    ...
    @Override
    public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException {
        try {
            //下面会通过Wrapper创建一个包装类对象
            //该对象是动态构建出来的,它属于Wrapper的一个子类,里面会拼接一个关键的方法invokeMethod(),拼接代码由Javassist动态生成
            final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type);
            //下面会创建一个实现了AbstractProxyInvoker的匿名内部类
            //其doInvoker()方法会直接委托给Wrapper对象的invokeMethod()方法
            return new AbstractProxyInvoker<T>(proxy, type, url) {
                @Override
                protected Object doInvoke(T proxy, String methodName, Class<?>[] parameterTypes, Object[] arguments) throws Throwable {
                    //当AbstractProxyInvoker.invoke()方法被调用时,便会执行到这里
                    //这里会通过类似于JDK反射的技术,调用本地实现类如DemoServiceImpl.sayHello()
                    //这个wrapper对象是由javassist技术动态生成的,已经对本地实现类进行包装
                    //这个动态生成的wrapper对象会通过javassist技术自己特有的方法
                    //在invokerMethod()方法被调用时执行本地实现类的目标方法
                    return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
                }
            };
        } catch (Throwable fromJavassist) {
            //使用JDK的反射去调用本地,这时没有动态生成的Wrapper类了
            Invoker<T> invoker = jdkProxyFactory.getInvoker(proxy, type, url);
            return invoker;
        }
    }
    ...
}

10.Dubbo的分层架构原理

(1)架构图说明

(2)各层简单介绍

(3)各层关系说明

(1)架构图说明

说明一: 左边淡蓝色背景的为服务消费方使用的接口,右边淡绿色背景的为服务提供方使用的接口,位于中轴线上的为双方都用到的接口。

说明二: 图中从下至上分为十层,各层均为单向依赖,右边的黑色箭头代表层之间的依赖关系。每一层都可以剥离上层被复用,其中Service和Config层为API,其它各层均为SPI。

说明三: 图中绿色小块的为扩展接口,蓝色小块为实现类,图中只显示用于关联各层的实现类。

说明四: 图中蓝色虚线为初始化过程,即启动时组装链,红色实线为方法调用过程,即运行时调用链。紫色三角箭头为继承,可以把子类看作父类的同一个节点,线上的文字为调用的方法。

(2)各层简单介绍

rust 复制代码
服务 -> 配置 -> 代理 -> 注册 -> 
路由 -> 监控 -> 调用 -> 
交换 -> 传输 -> 序列化

服配代注 路监调 交传序

一.Service服务接口层

与实际业务逻辑相关的,根据服务提供方和服务消费方的业务,设计对应的接口和实现。

arduino 复制代码
//Interface
//Implement

二.Config配置层

对外配置接口,以ServiceConfig、ReferenceConfig为中心,可以直接new配置类,也可以通过spring解析配置生成配置类。

arduino 复制代码
//ReferenceConfig
//ServiceConfig

三.Proxy服务代理层

服务接口透明代理,生成服务的客户端Stub和服务器端Skeleton,以ServiceProxy为中心,扩展接口为ProxyFactory。

arduino 复制代码
//Proxy
//ProxyFactory
//Invoker

四.Registry注册中心层

封装服务地址的注册与发现,以服务URL为中心,扩展接口为RegistryFactory、Registry、RegistryService。

arduino 复制代码
//NotifyListener
//Registry
//RegistryFactory
//RegistryDirectory
//RegistryProtocol

五.Cluster路由层

封装多个提供者的路由及负载均衡,并桥接注册中心。以Invoker为中心,扩展接口为Cluster、Directory、Router、LoadBalance。

arduino 复制代码
//Invoker
//Directory
//LoadBalance
//Cluster
//Router
//RouterFactory

六.Monitor监控层

RPC调用次数和调用时间监控,以Statistics为中心,扩展接口为MonitorFactory、Monitor、MonitorService。

arduino 复制代码
//MonitorFilter
//Monitor
//MonitorFactory

七.Protocol远程调用层

封装RPC调用,以Invocation、Result为中心,扩展接口为Protocol、Invoker、Exporter。

arduino 复制代码
//Filter
//Invoker
//DubboInvoker
//Protocol
//DubboProtocol
//Exporter
//DubboExporter
//DubboHandler

八.Exchange信息交换层

封装请求响应模式,同步转异步。以Request、Response为中心,扩展接口为Exchanger、ExchangeChannel、ExchangeClient、ExchangeServer。

arduino 复制代码
//ExchangeClient
//Exchanger
//ExchangeServer
//ExchangeHandler

九.Transport传输层

抽象Mina和Netty为统一接口,以message为中心,扩展接口为Channel、Transporter、Client、Server、Codec。

arduino 复制代码
//Client
//Transporter
//Server
//ChannelHandler
//Codec
//Dispatcher

十.Serialize数据序列化层

可复用的一些工具,扩展接口为Serialization、ObjectInput、ObjectOutput、ThreadPool。

arduino 复制代码
//ObjectOutput
//Serialization
//ObjectInput
//ThreadPool

(3)各层关系说明

说明一: 在RPC中,Protocol是核心层。也就是只要有Protocol+Invoker+Exporter就可以完成非透明的RPC调用,然后在Invoker的主过程上Filter拦截点。

说明二: 图中的Consumer和Provider是抽象概念,只是为了更直观呈现哪些类属于客户端和服务器端。不用Client和Server的原因是Dubbo使用Provider、Consumer、Registry、Monitor划分逻辑拓扑节点,保持概念统一。

说明三: 图中Cluster是外围概念,所以Cluster的目的是将多个Invoker伪装成一个Invoker。这样其他人只要关注Protocol层Invoker即可,Cluster的有无对其他层都不会造成影响,因为只有一个提供者时无需Cluster。

说明四: Proxy层封装了所有接口的透明化代理,而在其他层都以Invoker为中心。只有到了暴露给用户使用时,才用Proxy将Invoker转成接口,或将接口实现转成Invoker。也就是去掉Proxy层RPC是可以运行的,只是不那么透明,不那么看起来像调本地服务一样调远程服务。

说明五: Remoting实现是Dubbo协议的实现,如果选择RMI协议则整个Remoting都不会用上。Remoting内部再划分为Transport传输层和Exchange信息交换层。Transport层只负责单向消息传输,是对Mina、Netty、Grizzly的抽象,它也可以扩展UDP传输。Exchange层是在传输层之上封装了Request-Response语义。

说明六: Registry和Monitor实际上不算一层而是一个独立的节点,只是为了全局概览,用层的方式画在一起。

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