dubbo服务消费过程(一)

本文详细介绍了Dubbo服务消费的过程,包括服务引入、创建代理、服务调用的内部实现,如ReferenceBean、InvokerInvocationHandler、协议引用等。内容涵盖了从初始化入口ReferenceBean开始,经由protocol.refer创建invoker,通过ProxyFactory生成代理类,到最后的服务调用和容错处理,揭示了Dubbo在消费端的完整工作流程。
部署运行你感兴趣的模型镜像

如何实现服的消费

  • 生成远程服务的代理
  • 获取目标服务的url地址
  • 实现远程网络通信
  • 实现负载均衡
  • 实现集群容错

在这里插入图片描述
Invoker
在这里插入图片描述

服务引入

消费端的代码解析是从下面这段代码开始的

<dubbo:reference id="xxxService" interface="xxx.xxx.Service"/>

注解的方式的初始化入口是

ReferenceAnnotationBeanPostProcessor
->ReferenceBeanInvocationHandler.init
->ReferenceConfig.get() 获得一个远程代理类

ReferenceBean

服务引用的入口方法为 ReferenceBean 的 getObject 方法,该方法定义在 Spring 的 FactoryBean 接口中

/**
 * ReferenceFactoryBean
 */
public class ReferenceBean<T> extends ReferenceConfig<T> implements FactoryBean,
        ApplicationContextAware, InitializingBean, DisposableBean {
    private static final long serialVersionUID = 213195494150089726L;

    private transient ApplicationContext applicationContext;
    public ReferenceBean() {
        super();
    }
    public ReferenceBean(Reference reference) {
        super(reference);
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
     SpringExtensionFactory.addApplicationContext(applicationContext);
    }
    @Override 
    // 这是入口方法
    public Object getObject() {
        return get();
    }

    @Override
    public Class<?> getObjectType() {
        return getInterfaceClass();
    }
    @Override
    @Parameter(excluded = true)
    public boolean isSingleton() {
        return true;
    }
    /**
     * Initializes there Dubbo's Config Beans before @Reference bean autowiring
     */
    private void prepareDubboConfigBeans() {
        beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class);
        beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class);
        beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class);
        beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class);
        beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class);
        beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class);
        beansOfTypeIncludingAncestors(applicationContext, ConsumerConfig.class);
        beansOfTypeIncludingAncestors(applicationContext, ConfigCenterBean.class);
        beansOfTypeIncludingAncestors(applicationContext, MetadataReportConfig.class);
        beansOfTypeIncludingAncestors(applicationContext, MetricsConfig.class);
        beansOfTypeIncludingAncestors(applicationContext, SslConfig.class);
    }

    @Override
    @SuppressWarnings({"unchecked"})
    public void afterPropertiesSet() throws Exception {
        // 加载 dubbo的ConfigBean到ioc容器中
        prepareDubboConfigBeans();

        // 默认懒加载 可以通过@Reference(init = true)
        if (init == null) {
            init = false;
        }

        // eager init if necessary.
        if (shouldInit()) {
            getObject();
        }
    }

    @Override
    public void destroy() {
        // do nothing
    }
}

ReferenceConfig.get

 public synchronized T get() {
        if (destroyed) {
            throw new IllegalStateException("The invoker of ReferenceConfig(" + url + ") has already destroyed!");
        }
        // 如果当前接口的远程代理引用为空,则进行初始化
        if (ref == null) {
            init();
        }
        return ref;
    }

ReferenceConfig.init

    public synchronized void init() {
    	// 避免重复初始化
        if (initialized) {
            return;
        }
        if (bootstrap == null) {
            bootstrap = DubboBootstrap.getInstance();
            bootstrap.init(); 
        }
		// 检查和修改配置
        checkAndUpdateSubConfigs();

        //init serivceMetadata 初始化 服务元数据
        serviceMetadata.setVersion(version);
        serviceMetadata.setGroup(group);
        serviceMetadata.setDefaultGroup(group);
        serviceMetadata.setServiceType(getActualInterface());
        serviceMetadata.setServiceInterfaceName(interfaceName);
        // TODO, uncomment this line once service key is unified
        serviceMetadata.setServiceKey(URL.buildKey(interfaceName, group, version));
		// 检查本地服务
        checkStubAndLocal(interfaceClass);
        ConfigValidationUtils.checkMock(interfaceClass, this);

        Map<String, String> map = new HashMap<String, String>();
        map.put(SIDE_KEY, CONSUMER_SIDE);

        ReferenceConfigBase.appendRuntimeParameters(map);
        if (!ProtocolUtils.isGeneric(generic)) {
            String revision = Version.getVersion(interfaceClass, version);
            if (revision != null && revision.length() > 0) {
                map.put(REVISION_KEY, revision);
            }

            String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames();
            if (methods.length == 0) {
                logger.warn("No method found in service interface " + interfaceClass.getName());
                map.put(METHODS_KEY, ANY_VALUE);
            } else {
                map.put(METHODS_KEY, StringUtils.join(new HashSet<String>(Arrays.asList(methods)), COMMA_SEPARATOR));
            }
        }
        map.put(INTERFACE_KEY, interfaceName);
        AbstractConfig.appendParameters(map, getMetrics());
        AbstractConfig.appendParameters(map, getApplication());
        AbstractConfig.appendParameters(map, getModule());
        // remove 'default.' prefix for configs from ConsumerConfig
        // appendParameters(map, consumer, Constants.DEFAULT_KEY);
        AbstractConfig.appendParameters(map, consumer);
        AbstractConfig.appendParameters(map, this);
        Map<String, Object> attributes = null;
        if (CollectionUtils.isNotEmpty(getMethods())) {
            attributes = new HashMap<>();
            for (MethodConfig methodConfig : getMethods()) {
                AbstractConfig.appendParameters(map, methodConfig, methodConfig.getName());
                String retryKey = methodConfig.getName() + ".retry";
                if (map.containsKey(retryKey)) {
                    String retryValue = map.remove(retryKey);
                    if ("false".equals(retryValue)) {
                        map.put(methodConfig.getName() + ".retries", "0");
                    }
                }
                ConsumerModel.AsyncMethodInfo asyncMethodInfo = AbstractConfig.convertMethodConfig2AsyncInfo(methodConfig);
                if (asyncMethodInfo != null) {
//                    consumerModel.getMethodModel(methodConfig.getName()).addAttribute(ASYNC_KEY, asyncMethodInfo);
                    attributes.put(methodConfig.getName(), asyncMethodInfo);
                }
            }
        }
 		// 获取服务消费者 ip 地址
        String hostToRegistry = ConfigUtils.getSystemProperty(DUBBO_IP_TO_REGISTRY);
        if (StringUtils.isEmpty(hostToRegistry)) {
            hostToRegistry = NetUtils.getLocalHost();
        } else if (isInvalidLocalHost(hostToRegistry)) {
            throw new IllegalArgumentException("Specified invalid registry ip from property:" + DUBBO_IP_TO_REGISTRY + ", value:" + hostToRegistry);
        }
        map.put(REGISTER_IP_KEY, hostToRegistry);

        serviceMetadata.getAttachments().putAll(map);
        /******************上面都是参数组装********************/
		// 元数据中心注册
        ServiceRepository repository = ApplicationModel.getServiceRepository();
        ServiceDescriptor serviceDescriptor = repository.registerService(interfaceClass);
        repository.registerConsumer(
                serviceMetadata.getServiceKey(),
                attributes,
                serviceDescriptor,
                this,
                null,
                serviceMetadata);
		// 创建代理类引用 这个才是关键
        ref = createProxy(map);

        serviceMetadata.setTarget(ref);
        serviceMetadata.addAttribute(PROXY_CLASS_REF, ref);
        repository.lookupReferredService(serviceMetadata.getServiceKey()).setProxyObject(ref);

        initialized = true; // 设置已经初始化

        // dispatch a ReferenceConfigInitializedEvent since 2.7.4
        dispatch(new ReferenceConfigInitializedEvent(this, invoker));
    }

ReferenceConfig.createProxy

  1. 判断是否为本地调用,如果是则使用injvm协议进行调用
  2. 判断是否为点对点调用,如果是则把url保存到urls集合中,如果url为1,进入步骤4,如果urls>1,则执行5 3. 如果是配置了注册中心,遍历注册中心,把url添加到urls集合,url为1,进入步骤4,如果urls>1,则执行5
  3. 直连构建invoker
  4. 构建invokers集合,通过cluster合并多个invoker
  5. 最后调用 ProxyFactory 生成代理类
    private T createProxy(Map<String, String> map) {
    	// 判断是否是在同一个jvm进程中调用
        if (shouldJvmRefer(map)) {
            URL url = new URL(LOCAL_PROTOCOL, LOCALHOST_VALUE, 0, interfaceClass.getName()).addParameters(map);
            invoker = REF_PROTOCOL.refer(interfaceClass, url);
            if (logger.isInfoEnabled()) {
                logger.info("Using injvm service " + interfaceClass.getName());
            }
        } else {
            urls.clear();
            // @Reference(url = "http://xxx") 直连方式
            // url如果不为空,说明是点对点通信
            if (url != null && url.length() > 0) { // user specified URL, could be peer-to-peer address, or register center's address.
                String[] us = SEMICOLON_SPLIT_PATTERN.split(url);
                if (us != null && us.length > 0) {
                    for (String u : us) {
                        URL url = URL.valueOf(u);
                        if (StringUtils.isEmpty(url.getPath())) {
                            url = url.setPath(interfaceName);
                        }
                        // 检测url协议是否为registry,若是,表明用户想使用的指定的注册中心
                        if (UrlUtils.isRegistry(url)) {
                        	// 将map转换为查询字符串,并作为refer参数的值添加到url中
                            urls.add(url.addParameterAndEncoded(REFER_KEY, StringUtils.toQueryString(map)));
                        } else {
                        	// 合并url,移除服务提供者的一些配置(这些配置来源用户配置的url属性)
                        	// 比如线程池相关配置。并保留服务提供者的部分配置,比如版本,group,时间戳等
                        	// 最后合将合并的配置设置url查询字符串中
                            urls.add(ClusterUtils.mergeUrl(url, map));
                        }
                    }
                }
            } else { // assemble URL from register center's configuration
                // if protocols not injvm checkRegistry
                if (!LOCAL_PROTOCOL.equalsIgnoreCase(getProtocol())) {
                	// 检验注册中心的配置以及是否必要从配置中心组装url
                    checkRegistry();
                    // 这里的代码实现和服务端类似,也是根据注册中心配置解析等到的url
                    // 这里的url:registry://192.168.0.4:2181/org.apache.dubbo.registry.RegistryService
                    List<URL> us = ConfigValidationUtils.loadRegistries(this, false);
                    if (CollectionUtils.isNotEmpty(us)) {
                        for (URL u : us) {
                            URL monitorUrl = ConfigValidationUtils.loadMonitor(this, u);
                            if (monitorUrl != null) {
                                map.put(MONITOR_KEY, URL.encode(monitorUrl.toFullString()));
                            }
                            urls.add(u.addParameterAndEncoded(REFER_KEY, StringUtils.toQueryString(map)));
                        }
                    }
                    // 如果没有配置注册中心,则报错
                    if (urls.isEmpty()) {
                        throw new IllegalStateException("No such any registry to reference " + interfaceName + " on the consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", please config <dubbo:registry address=\"...\" /> to your spring config.");
                    }
                }
            }
			// 如果配置了一个注册中心或者一个服务提供者,直接使用refprotocol.refer
            if (urls.size() == 1) {
            	// Protocol$Adaptive --> RegistryProtocol.refer
                invoker = REF_PROTOCOL.refer(interfaceClass, urls.get(0));
            } else { // 配置多个注册中心
                List<Invoker<?>> invokers = new ArrayList<Invoker<?>>();
                URL registryURL = null;
                for (URL url : urls) { // 遍历urls生成多个invoker
                    invokers.add(REF_PROTOCOL.refer(interfaceClass, url));
                    if (UrlUtils.isRegistry(url)) {
                        registryURL = url; // use last registry url
                    }
                }
                if (registryURL != null) { // 如果registryURL不为空,构建静态directory
                    // 使用ZoneAwareCluster
                    URL u = registryURL.addParameterIfAbsent(CLUSTER_KEY, ZoneAwareCluster.NAME);
                    // 通过Cluster将多个invoker合并ZoneAwareClusterInvoker(StaticDirectory) -> FailoverClusterInvoker(RegistryDirectory, routing happens here)-> Invoker
                    invoker = CLUSTER.join(new StaticDirectory(u, invokers));
                } else { // not a registry url, must be direct invoke.
                    invoker = CLUSTER.join(new StaticDirectory(invokers));
                }
            }
        }
		// 检查invoker的有效性
        if (shouldCheck() && !invoker.isAvailable()) {
            throw new IllegalStateException("Failed to check the status of the service "
                    + interfaceName
                    + ". No provider available for the service "
                    + (group == null ? "" : group + "/")
                    + interfaceName +
                    (version == null ? "" : ":" + version)
                    + " from the url "
                    + invoker.getUrl()
                    + " to the consumer "
                    + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion());
        }
        if (logger.isInfoEnabled()) {
            logger.info("Refer dubbo service " + interfaceClass.getName() + " from url " + invoker.getUrl());
        }
        /**
         * @since 2.7.0
         * ServiceData Store
         */
        String metadata = map.get(METADATA_KEY);
        WritableMetadataService metadataService = WritableMetadataService.getExtension(metadata == null ? DEFAULT_METADATA_STORAGE_TYPE : metadata);
        if (metadataService != null) {
            URL consumerURL = new URL(CONSUMER_PROTOCOL, map.remove(REGISTER_IP_KEY), 0, map.get(INTERFACE_KEY), map);
            metadataService.publishServiceDefinition(consumerURL);
        }
        // create service proxy 创建服务代理类
        return (T) PROXY_FACTORY.getProxy(invoker);
    }

protocol.refer

通过指定的协议来调用refer生成一个invoker对象,invoker前面讲过,它是一个代理对象。那么在当前的消费端而言,invoker主要用于执行远程调用。这个protocol,又是一个自适应扩展点,它得到的是一个Protocol$Adaptive.

private static final Protocol REF_PROTOCOL = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();

根据当前的协议url,得到一个指定的扩展点,传递进来的参数中,协议地址为registry://,所以,我们可以直接定位到RegistryProtocol.refer代码
Protocol$Adaptive中的refer方法

  public org.apache.dubbo.rpc.Invoker refer(java.lang.Class arg0, org.apache.dubbo.common.URL arg1) throws org.apache.dubbo.rpc.RpcException {
        if (arg1 == null) throw new IllegalArgumentException("url == null");
        org.apache.dubbo.common.URL url = arg1;
        String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
        if (extName == null)
            throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.Protocol) name from url (" + url.toString() + ") use keys([protocol])");
        org.apache.dubbo.rpc.Protocol extension = (org.apache.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);
        return extension.refer(arg0, arg1);
    }

根据当前的协议扩展名registry, 获得一个被包装过的RegistryProtocol

RegistryProtocol.refer

  • (1) 组装注册中心协议url
  • (2) 判断是否配置legroup,如果有,则cluster=getMergeableCluster(),构建invoker
  • (3) doRefer构建invoker
   public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
   		// (1) 组装注册中心协议rul
   		// url: zookeeper://192.168.0.4:2181/org.apache.dubbo.registry.RegistryService?xxx
        url = getRegistryUrl(url);
        // registryFactory-> RegistryFactory$Aaptive -> zookeeperRegistryFactory.getRegistry
        // registry 最终返回 zookeeperRegistry 使用curator建立到zookeeper的连接 
        Registry registry = registryFactory.getRegistry(url);
        if (RegistryService.class.equals(type)) {
            return proxyFactory.getInvoker((T) registry, type, url);
        }

        // group="a,b" or group="*"
        // 解析group参数,根据group决定cluster的类型
        Map<String, String> qs = StringUtils.parseQueryString(url.getParameterAndDecoded(REFER_KEY));
        String group = qs.get(GROUP_KEY);
        if (group != null && group.length() > 0) {
            if ((COMMA_SPLIT_PATTERN.split(group)).length > 1 || "*".equals(group)) {
            	// 通过SPI加载MergeableCluster实例,并调用doRefer继续执行
                return doRefer(getMergeableCluster(), registry, type, url);
            }
        }
        // 构建invoker 调用doRefer继续执行服务引用逻辑
        return doRefer(cluster, registry, type, url);
    }
    // 根据配置的协议组装url
    protected URL getRegistryUrl(URL url) {
        return URLBuilder.from(url)
                .setProtocol(url.getParameter(REGISTRY_KEY, DEFAULT_REGISTRY))
                .removeParameter(REGISTRY_KEY)
                .build();
    }

RegistryProtocol.doRefer

  • 构建一个RegistryDirectory
  • 构建一个consumer://协议的地址注册到注册中心
  • 订阅zookeeper中节点的变化
  • 调用cluster.join方法
  private <T> Invoker<T> doRefer(Cluster cluster, Registry registry, Class<T> type, URL url) {
  		// RegistryDirectory初始化
        RegistryDirectory<T> directory = new RegistryDirectory<T>(type, url);
        // 设置注册中心和协议
        directory.setRegistry(registry);
        directory.setProtocol(protocol);
        // all attributes of REFER_KEY
        Map<String, String> parameters = new HashMap<String, String>(directory.getUrl().getParameters());
        // url:consumer://192.168.0.4/com.test.dubbo.DemoService?xxx
        URL subscribeUrl = new URL(CONSUMER_PROTOCOL, parameters.remove(REGISTER_IP_KEY), 0, type.getName(), parameters);
        // 注册服务消费者,在consumers 目前下新节点
        if (!ANY_VALUE.equals(url.getServiceInterface()) && url.getParameter(REGISTER_KEY, true)) {
            directory.setRegisteredConsumerUrl(getRegisteredConsumerUrl(subscribeUrl, url));
             // 注册consumer://协议的url
            registry.register(directory.getRegisteredConsumerUrl());
        }
        // 构建routerChain
        directory.buildRouterChain(subscribeUrl);
        // 订阅 providers,configurators,routers等节点数据
        directory.subscribe(subscribeUrl.addParameter(CATEGORY_KEY,
                PROVIDERS_CATEGORY + "," + CONFIGURATORS_CATEGORY + "," + ROUTERS_CATEGORY));
		// 一个注册中心可能有多个服务提供者,因此这里需要将多个服务提供者合并为一个 后面负责均衡用到
		// 这里返回的invoker,应该是MockClusterWrapper(FailOverCluster(directory))
        Invoker invoker = cluster.join(directory);
        return invoker;
    }

doRefer 方法创建一个 RegistryDirectory 实例,然后生成服务者消费者链接,并向注册中心进行注册。注册完毕后,紧接着订阅 providers、configurators、routers 等节点下的数据。完成订阅后,RegistryDirectory 会收到这几个节点下的子节点信息。由于一个服务可能部署在多台服务器上,这样就会在 providers 产生多个节点,这个时候就需要 Cluster 将多个服务节点合并为一个,并生成一个 Invoker。关于 RegistryDirectory 和 Cluster,这里不再分析,后面单独分析。

proxyFactory.getProxy创建代理

ReferenceConfig.createProxy方法中的最后一行,拿到invoker之后,会调用获得一个动态代理类

 return (T) PROXY_FACTORY.getProxy(invoker);

proxyFactory是一个SPI扩展点 可以直接看StubProxyFactoryWrapper(JavassistProxyFactory)
JavassistProxyFactory中没有getProxy(xx)一个参数的方法会调用其父类的方法AbstractProxyFactory#getProxy(Invoker<T>)

可以直接从AbstractProxyFactory.getProxy分析

AbstractProxyFactory.getProxy

public abstract class AbstractProxyFactory implements ProxyFactory {
    private static final Class<?>[] INTERNAL_INTERFACES = new Class<?>[]{
            EchoService.class, Destroyable.class
    };

    @Override
    public <T> T getProxy(Invoker<T> invoker) throws RpcException {
    	// 调用重载方法
        return getProxy(invoker, false);
    }

    @Override
    public <T> T getProxy(Invoker<T> invoker, boolean generic) throws RpcException {
        Set<Class<?>> interfaces = new HashSet<>();
		// 获取接口配置
        String config = invoker.getUrl().getParameter(INTERFACES);
        if (config != null && config.length() > 0) {
        	// 切分接口列表
            String[] types = COMMA_SPLIT_PATTERN.split(config);
            if (types != null && types.length > 0) {
                for (int i = 0; i < types.length; i++) {
                    // TODO can we load successfully for a different classloader?.
                    interfaces.add(ReflectUtils.forName(types[i]));
                }
            }
        }

        if (!GenericService.class.isAssignableFrom(invoker.getInterface()) && generic) {
            interfaces.add(com.alibaba.dubbo.rpc.service.GenericService.class);
        }
		// 添加接口
        interfaces.add(invoker.getInterface());
        // 添加服务类接口 EchoService.class, Destroyable.class
        interfaces.addAll(Arrays.asList(INTERNAL_INTERFACES));
		// 调用模板重载方法 
        return getProxy(invoker, interfaces.toArray(new Class<?>[0]));
    }
	// 模板方法 由子类实现 如:JavassistProxyFactory.getProxy
    public abstract <T> T getProxy(Invoker<T> invoker, Class<?>[] types);

}

JavassistProxyFactory.getProxy

public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
   // 生成 Proxy 子类(Proxy 是抽象类)。并调用 Proxy 子类的 newInstance 方法创建 Proxy 实例
    return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
}

通过 Proxy 的 getProxy 方法获取 Proxy 子类,然后创建 InvokerInvocationHandler 对象,并将该对象传给 newInstance 生成 Proxy 实例
InvokerInvocationHandler 实现 JDK 的 InvocationHandler 接口,具体的用途是拦截接口类调用

Proxy.getProxy

  public static Proxy getProxy(Class<?>... ics) {
		// 调用重载方法
        return getProxy(ClassUtils.getClassLoader(Proxy.class), ics);
    }
    public static Proxy getProxy(ClassLoader cl, Class<?>... ics) {
        if (ics.length > MAX_PROXY_COUNT) {
            throw new IllegalArgumentException("interface limit exceeded");
        }
        StringBuilder sb = new StringBuilder();
        // 遍历接口列表
        for (int i = 0; i < ics.length; i++) {
            String itf = ics[i].getName();
            // 检查类型是否为接口
            if (!ics[i].isInterface()) {
                throw new RuntimeException(itf + " is not a interface.");
            }
            Class<?> tmp = null;
            try {
            	// 重新加载接口类
                tmp = Class.forName(itf, false, cl);
            } catch (ClassNotFoundException e) {
            }
			// 检测接口是否相同,这里tmp有可能为空
            if (tmp != ics[i]) {
                throw new IllegalArgumentException(ics[i] + " is not visible from class loader");
            }
			// 拼接接口全限定名,分割符为
            sb.append(itf).append(';');
        }
		// 使用拼接后的接口名作为key
			//eg: com.alibaba.dubbo.rpc.service.EchoService;com.test.dubbo.DemoService;org.apache.dubbo.rpc.service.Destroyable;
        String key = sb.toString();

        // get cache by class loader.
        final Map<String, Object> cache;
        synchronized (PROXY_CACHE_MAP) {
            cache = PROXY_CACHE_MAP.computeIfAbsent(cl, k -> new HashMap<>());
        }

        Proxy proxy = null;
        synchronized (cache) {
            do {
            	// 从缓存中获取Reference<Proxy>实例
                Object value = cache.get(key);
                if (value instanceof Reference<?>) {
                    proxy = (Proxy) ((Reference<?>) value).get();
                    if (proxy != null) {
                        return proxy;
                    }
                }
				// 并发控制,保证只有一个线程可以进行后续操作
                if (value == PENDING_GENERATION_MARKER) {
                    try {
                    	// 其他线程在此处进行等待
                        cache.wait();
                    } catch (InterruptedException e) {
                    }
                } else {
                	// 放置标志为到缓存,并跳出while循环进行后续操作
                    cache.put(key, PENDING_GENERATION_MARKER);
                    break;
                }
            }
            while (true);
        }

        long id = PROXY_CLASS_COUNTER.getAndIncrement();
        String pkg = null;
        ClassGenerator ccp = null, ccm = null;
        try {
        	// 创建ClassGenerator对象
            ccp = ClassGenerator.newInstance(cl);

            Set<String> worked = new HashSet<>();
            List<Method> methods = new ArrayList<>();
            for (int i = 0; i < ics.length; i++) {
            	// 检测接口访问级别是否为protocted或private
                if (!Modifier.isPublic(ics[i].getModifiers())) {
                	// 获取接口报名
                    String npkg = ics[i].getPackage().getName();
                    if (pkg == null) {
                        pkg = npkg;
                    } else {
                    	// 非public级别的接口必须在同一个包下,否则抛出异常
                        if (!pkg.equals(npkg)) {
                            throw new IllegalArgumentException("non-public interfaces from different packages");
                        }
                    }
                }
                // 添加接口到ClassGenerator中
                ccp.addInterface(ics[i]);
				// 遍历接口方法
                for (Method method : ics[i].getMethods()) {
                	// 获取方法描述,可以理解为方法签名
                    String desc = ReflectUtils.getDesc(method);
                    // 如果方法描述字符串已在 worked 中,则忽略。考虑这种情况,
                	// A 接口和 B 接口中包含一个完全相同的方法
                    if (worked.contains(desc) || Modifier.isStatic(method.getModifiers())) {
                        continue;
                    }
                    if (ics[i].isInterface() && Modifier.isStatic(method.getModifiers())) {
                        continue;
                    }
                    worked.add(desc);
                    int ix = methods.size();
                    // 获取方法返回值类型
                    Class<?> rt = method.getReturnType();
                    Class<?>[] pts = method.getParameterTypes();
					// 生成 Object[] args = new Object[1...N]
                    StringBuilder code = new StringBuilder("Object[] args = new Object[").append(pts.length).append("];");
                    for (int j = 0; j < pts.length; j++) {
                   		// 生成 args[1...N] = ($w)$1...N;
                        code.append(" args[").append(j).append("] = ($w)$").append(j + 1).append(";");
                    }
                    code.append(" Object ret = handler.invoke(this, methods[").append(ix).append("], args);");
                     // 返回值不为 void
                    if (!Void.TYPE.equals(rt)) {
                    	// 生成返回语句,形如 return (java.lang.String) ret;
                        code.append(" return ").append(asArgument(rt, "ret")).append(";");
                    }
                    methods.add(method);
                    // 添加方法名、访问控制符、参数列表、方法代码等信息到 ClassGenerator 中 
                    ccp.addMethod(method.getName(), method.getModifiers(), rt, pts, method.getExceptionTypes(), code.toString());
                }
            }

            if (pkg == null) {
                pkg = PACKAGE_NAME;
            }

            // 构建接口代理类名称:pkg + ".proxy" + id,比如 org.apache.dubbo.proxy0
            String pcn = pkg + ".proxy" + id;
            ccp.setClassName(pcn);
            ccp.addField("public static java.lang.reflect.Method[] methods;");
             // 生成 private java.lang.reflect.InvocationHandler handler
            ccp.addField("private " + InvocationHandler.class.getName() + " handler;");
            ccp.addConstructor(Modifier.PUBLIC, new Class<?>[]{InvocationHandler.class}, new Class<?>[0], "handler=$1;");
            // 为接口代理类添加默认构造方法
            ccp.addDefaultConstructor();
            // 生成接口代理类
            Class<?> clazz = ccp.toClass();
            clazz.getField("methods").set(null, methods.toArray(new Method[0]));

            // 构建 Proxy 子类名称,比如 Proxy1,Proxy2 等
            String fcn = Proxy.class.getName() + id;
            ccm = ClassGenerator.newInstance(cl);
            ccm.setClassName(fcn);
            ccm.addDefaultConstructor();
            ccm.setSuperClass(Proxy.class);
            ccm.addMethod("public Object newInstance(" + InvocationHandler.class.getName() + " h){ return new " + pcn + "($1); }");
            // 生成 Proxy 实现类
            Class<?> pc = ccm.toClass();
            // 通过反射创建 Proxy 实例
            proxy = (Proxy) pc.newInstance();
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            // 释放资源
            if (ccp != null) {
                ccp.release();
            }
            if (ccm != null) {
                ccm.release();
            }
            synchronized (cache) {
                if (proxy == null) {
                    cache.remove(key);
                } else {
                	// 写缓存
                    cache.put(key, new WeakReference<Proxy>(proxy));
                }
                // 唤醒其他等待线程
                cache.notifyAll();
            }
        }
        return proxy;
    }

在这里插入图片描述
最终会生成如proxy0类

package org.apache.dubbo.common.bytecode;

public class proxy0 implements com.test.dubbo.DemoService, EchoService, DemoService {

    public static java.lang.reflect.Method[] methods;

    private java.lang.reflect.InvocationHandler handler;

    public proxy0() {
    }
    public proxy0(java.lang.reflect.InvocationHandler arg0) {
        handler = $1;
    }

    public java.lang.String sayHello(java.lang.String arg0) {
    	// 将参数存储到 Object 数组中
        Object[] args = new Object[1];
        args[0] = ($w) $1;
        // 调用 InvocationHandler 实现类的 invoke 方法得到调用结果
        Object ret = handler.invoke(this, methods[0], args);
        // 返回调用结果
        return (java.lang.String) ret;
    }
    /** 回声测试方法 */
    public Object $echo(Object object) {
        Object[] arrobject = new Object[]{object};
        Object object2 = this.handler.invoke(this, methods[1], arrobject);
        return object2;
   }
}

从这个sayHello方法可以看出,我们通过@Reference注入的一个对象实例本质上就是一个动态代理类,通过调用这个类中的方法,会触发
handler.invoke(), 而这个handler就是InvokerInvocationHandler

服务调用

proxy0#sayHello(String)> InvokerInvocationHandler#invoke(Object, Method, Object[])> MockClusterInvoker#invoke(Invocation)> AbstractClusterInvoker#invoke(Invocation)> FailoverClusterInvoker#doInvoke(Invocation, List<Invoker<T>>, LoadBalance)> Filter#invoke(Invoker, Invocation)  // 包含多个 Filter 调用> ListenerInvokerWrapper#invoke(Invocation)> AbstractInvoker#invoke(Invocation)> DubboInvoker#doInvoke(Invocation)> ReferenceCountExchangeClient#request(Object, int)> HeaderExchangeClient#request(Object, int)> HeaderExchangeChannel#request(Object, int)> AbstractPeer#send(Object)> AbstractClient#send(Object, boolean)> NettyChannel#send(Object, boolean)> NioClientSocketChannel#write(Object)

消费者服务调用 invoker的链条调用 回顾上面的Proxy0$sayHello()调用 handler.invoke

 public java.lang.String sayHello(java.lang.String arg0) {
    	// 将参数存储到 Object 数组中
        Object[] args = new Object[1];
        args[0] = ($w) $1;
        // 调用 InvocationHandler 实现类的 invoke 方法得到调用结果
        Object ret = handler.invoke(this, methods[0], args);
        // 返回调用结果
        return (java.lang.String) ret;
    }

proxy0.handler是在JavassistProxyFactory.getProxy获取代理类时构造的,入口InvokerInvocationHandler

 return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));

InvokerInvocationHandler

public class InvokerInvocationHandler implements InvocationHandler {
    private static final Logger logger = LoggerFactory.getLogger(InvokerInvocationHandler.class);
    private final Invoker<?> invoker;

    public InvokerInvocationHandler(Invoker<?> handler) {
        this.invoker = handler;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        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)) {
                return invoker.toString();
            } else if ("$destroy".equals(methodName)) {
                invoker.destroy();
                return null;
            } else if ("hashCode".equals(methodName)) {
                return invoker.hashCode();
            }
        } else if (parameterTypes.length == 1 && "equals".equals(methodName)) {
            return invoker.equals(args[0]);
        }
        // 将method和args封装到RpcInvocation中,传输对象,并执行后续的调用
        RpcInvocation rpcInvocation = new RpcInvocation(method, invoker.getInterface().getName(), args);
        rpcInvocation.setTargetServiceUniqueName(invoker.getUrl().getServiceKey());
		// 这个invoker是MockClusterInvoker 是通过Cluster的扩展点的包装类MockClusterWrapper构建的
        return invoker.invoke(rpcInvocation).recreate();
    }
}

MockClusterInvoker.invoke

Mock,在这里面有两个逻辑

  1. 是否客户端强制配置了mock调用,那么在这种场景中主要可以用来解决服务端还没开发好的时候
    直接使用本地数据进行测试
  2. 是否出现了异常,如果出现异常则使用配置好的Mock类来实现服务的降级
public class MockClusterInvoker<T> implements Invoker<T> {
    private static final Logger logger = LoggerFactory.getLogger(MockClusterInvoker.class);
    private final Directory<T> directory;
    private final Invoker<T> invoker;
    public MockClusterInvoker(Directory<T> directory, Invoker<T> invoker) {
        this.directory = directory;
        this.invoker = invoker;
    }
    @Override
    public URL getUrl() {
        return directory.getUrl();
    }
    @Override
    public boolean isAvailable() {
        return directory.isAvailable();
    }
    @Override
    public void destroy() {
        this.invoker.destroy();
    }
    @Override
    public Class<T> getInterface() {
        return directory.getInterface();
    }

    @Override
    public Result invoke(Invocation invocation) throws RpcException {
        Result result = null;
        // 获取mock配置
        String value = directory.getUrl().getMethodParameter(invocation.getMethodName(), MOCK_KEY, Boolean.FALSE.toString()).trim();
        if (value.length() == 0 || "false".equalsIgnoreCase(value)) {
            //no mock
            // 无mock逻辑,直接调用其他Invoker对象的inoker方法
            // 比如: FailOverCluster 可以通过:@Reference(cluster="failover")配置
            result = this.invoker.invoke(invocation);
        } else if (value.startsWith("force")) {
            if (logger.isWarnEnabled()) {
                logger.warn("force-mock: " + invocation.getMethodName() + " force-mock enabled , url : " + directory.getUrl());
            }
            //force:direct mock
            // force:xx 直接执行mock逻辑,不乏其远程调用
            result = doMockInvoke(invocation, null);
        } else {
            //fail-mock
            // fail:xxx 表示消费方调用服务失败后,再执行mock逻辑,不抛出异常
            try {
            	// 调用其他的Invoker对象的invoke方法
                result = this.invoker.invoke(invocation);

                //fix:#4585 返回有异常情况
                if(result.getException() != null && result.getException() instanceof RpcException){
                    RpcException rpcException= (RpcException)result.getException();
                    if(rpcException.isBiz()){ // 业务异常直接返回
                        throw  rpcException;
                    }else { 
                    	// 非业务异常 服务降级mock逻辑
                        result = doMockInvoke(invocation, rpcException);
                    }
                }

            } catch (RpcException e) {
                if (e.isBiz()) { // 业务异常直接返回
                    throw e;
                }
                if (logger.isWarnEnabled()) {
                    logger.warn("fail-mock: " + invocation.getMethodName() + " fail-mock enabled , url : " + directory.getUrl(), e);
                }
                // 非业务异常 调用降级mock逻辑
                result = doMockInvoke(invocation, e);
            }
        }
        return result;
    }
    // 省略其他方法 
}    

AbstractClusterInvoker.invoke

下一个invoke,应该是FailoverClusterInvoker,它本身没有invoke方法,直接进入其父类AbstractClusterInvoker的invoker方法,有回调它的模板方法doInvoke

public abstract class AbstractClusterInvoker<T> implements Invoker<T> {
	// 保存从注册中心的拉取的所有invoker 目录  
    protected Directory<T> directory;
    protected boolean availablecheck; // 可用性检查
    private AtomicBoolean destroyed = new AtomicBoolean(false);
    // 粘性invoker 是否支持粘性调用
    private volatile Invoker<T> stickyInvoker = null;
 	@Override
    public Result invoke(final Invocation invocation) throws RpcException {
        checkWhetherDestroyed();
        // binding attachments into invocation.
        //  隐式参数
        // 绑定attachments,Dubbo中,可以通过 RpcContext 上的 setAttachment 和 getAttachment 
        // 在服务消费方和提供方之间进行参数的隐式传递,所以这段代码中会去绑定attachments
        Map<String, String> contextAttachments = RpcContext.getContext().getAttachments();
        if (contextAttachments != null && contextAttachments.size() != 0) {
            ((RpcInvocation) invocation).addAttachments(contextAttachments);
        }
        // 通过list获取invoker列表,这个列表是从directory里面获得的
        List<Invoker<T>> invokers = list(invocation);
        // 加载loadBalance
        LoadBalance loadbalance = initLoadBalance(invokers, invocation);
        RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
        return doInvoke(invocation, invokers, loadbalance);
    }
    protected List<Invoker<T>> list(Invocation invocation) throws RpcException {
    	// 调用Directory的list方法列举Invoker
        return directory.list(invocation);
    }
	// 初始化负载均衡策略
  	protected LoadBalance initLoadBalance(List<Invoker<T>> invokers, Invocation invocation) {
  	// 通过SPI获取LoadBalance  默认 random 
        if (CollectionUtils.isNotEmpty(invokers)) {
            return ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(invokers.get(0).getUrl()
                    .getMethodParameter(RpcUtils.getMethodName(invocation), LOADBALANCE_KEY, DEFAULT_LOADBALANCE));
        } else {
            return ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(DEFAULT_LOADBALANCE);
        }
    }
}

FailoverClusterInvoker.doInvoke

容错机制
容错的逻辑:failover失败重试

  • 获得重试的次数,并且进行循环
  • 获得目标服务,并且记录当前已经调用过的目标服务防止下次继续将请求发送过去
  • 如果执行成功,则返回结果
  • 如果出现异常,判断是否为业务异常,如果是则抛出,否则,进行下一次重试
  public Result doInvoke(Invocation invocation, final List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
        List<Invoker<T>> copyInvokers = invokers;
        checkInvokers(copyInvokers, invocation);
        String methodName = RpcUtils.getMethodName(invocation);
        // 获取重试次数 默认2次
        int len = getUrl().getMethodParameter(methodName, RETRIES_KEY, DEFAULT_RETRIES) + 1;
        if (len <= 0) {
            len = 1;
        }
        // retry loop.
        RpcException le = null; // last exception.
        List<Invoker<T>> invoked = new ArrayList<Invoker<T>>(copyInvokers.size()); // invoked invokers.
        Set<String> providers = new HashSet<String>(len);
        // 循环调用,失败重试
        for (int i = 0; i < len; i++) {
            if (i > 0) {
                checkWhetherDestroyed();
                // 在进行重试前重新列举 Invoker,这样做的好处是,如果某个服务挂了,
                // 通过调用 list 可得到最新可用的 Invoker 列表
                copyInvokers = list(invocation);
                // 对 copyinvokers 进行判空检查
                checkInvokers(copyInvokers, invocation);
            }
            // 通过负载均衡选择invoker
            Invoker<T> invoker = select(loadbalance, invocation, copyInvokers, invoked);
            // 记录已经调用过的服务,下次调用会进行过滤
            invoked.add(invoker);
            // 设置 invoked 到 RPC 上下文中
            RpcContext.getContext().setInvokers((List) invoked);
            try {
            	// 服务调用成功,直接返回
                Result result = invoker.invoke(invocation);
                if (le != null && logger.isWarnEnabled()) {
                    logger.warn("Although retry the method " + methodName
                            + " in the service " + getInterface().getName()
                            + " was successful by the provider " + invoker.getUrl().getAddress()
                            + ", but there have been failed providers " + providers
                            + " (" + providers.size() + "/" + copyInvokers.size()
                            + ") from the registry " + directory.getUrl().getAddress()
                            + " on the consumer " + NetUtils.getLocalHost()
                            + " using the dubbo version " + Version.getVersion() + ". Last error is: "
                            + le.getMessage(), le);
                }
                return result;
            } catch (RpcException e) {
                if (e.isBiz()) { // 如果是业务异常,直接抛出不进行重试
                    throw e;
                }
                le = e; // 记录异常信息,进行下一次循环
            } catch (Throwable e) {
                le = new RpcException(e.getMessage(), e);
            } finally {
                providers.add(invoker.getUrl().getAddress());
            }
        }
        // 若重试失败,则抛出异常
        throw new RpcException(le.getCode(), "Failed to invoke the method "
                + methodName + " in the service " + getInterface().getName()
                + ". Tried " + len + " times of the providers " + providers
                + " (" + providers.size() + "/" + copyInvokers.size()
                + ") from the registry " + directory.getUrl().getAddress()
                + " on the consumer " + NetUtils.getLocalHost() + " using the dubbo version "
                + Version.getVersion() + ". Last error is: "
                + le.getMessage(), le.getCause() != null ? le.getCause() : le);
    }

toInvokers

RegistryDirectory
在RegistryDirectory中有一个成员属性,保存了服务地方地址对应的invoke信息

private volatile Map<String, Invoker<T>> urlInvokerMap;

toInvokers
这个invoker是动态的,基于注册中心的变化而变化的。它的初始化过程的链路是
RegistryDirectory.notify->refreshInvoker->toInvokers

 if (enabled) {
    invoker = new InvokerDelegate<>(protocol.refer(serviceType, url), url, providerUrl);
 }

基于protocol.refer来构建的invoker,并且使用InvokerDelegate进行了委托,在DubboProtocol中,
是这样构建invoker的。返回的是一个DubboInvoker对象

	// AbstractProtocol#refer
   @Override
   public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
       return new AsyncToSyncInvoker<>(protocolBindingRefer(type, url));
   }
   // DubboProtocol#protocolBindingRefer
    public <T> Invoker<T> protocolBindingRefer(Class<T> serviceType, URL url) throws RpcException {
        optimizeSerialization(url);
        // create rpc invoker.
        DubboInvoker<T> invoker = new DubboInvoker<T>(serviceType, url, getClients(url), invokers);
        invokers.add(invoker);
        return invoker;
    }

综合上述通过url转成的invoker是
InvokerDelegate
->QosProtocolWrapper->ProtocolListenerWrapper->ProtocolFilterWrapper
->AbstractProtocol->DubboProtocol
->AsyncToSyncInvoker // 异步到同步invoke
->DubboInvoker

DubboInvoker

AbstractInvoker#invoke

// 对Invocation的attachments进行处理,把attachment加入到Invocation中
 public Result invoke(Invocation inv) throws RpcException {
        // if invoker is destroyed due to address refresh from registry, let's allow the current invoke to proceed
        if (destroyed.get()) {
            logger.warn("Invoker for service " + this + " on consumer " + NetUtils.getLocalHost() + " is destroyed, "
                    + ", dubbo version is " + Version.getVersion() + ", this invoker should not be used any longer");
        }
        RpcInvocation invocation = (RpcInvocation) inv;
        // 设置invoker
        invocation.setInvoker(this);
        if (CollectionUtils.isNotEmptyMap(attachment)) {
        	// 设置attachment
            invocation.addAttachmentsIfAbsent(attachment);
        }
        Map<String, String> contextAttachments = RpcContext.getContext().getAttachments();
        if (CollectionUtils.isNotEmptyMap(contextAttachments)) {
  			// 添加 contextAttachments 到 RpcInvocation#attachment 变量中
            invocation.addAttachments(contextAttachments);
        }
		// 设置调用模式 同步/异步调用
        invocation.setInvokeMode(RpcUtils.getInvokeMode(url, invocation));
        // 设置异步调用Id
        RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);

        AsyncRpcResult asyncResult;
        try {
        	// 抽象方法,有子类实现
            asyncResult = (AsyncRpcResult) doInvoke(invocation);
        } catch (InvocationTargetException e) { // biz exception
            Throwable te = e.getTargetException();
            if (te == null) {
                asyncResult = AsyncRpcResult.newDefaultAsyncResult(null, e, invocation);
            } else {
                if (te instanceof RpcException) {
                    ((RpcException) te).setCode(RpcException.BIZ_EXCEPTION);
                }
                asyncResult = AsyncRpcResult.newDefaultAsyncResult(null, te, invocation);
            }
        } catch (RpcException e) {
            if (e.isBiz()) {
                asyncResult = AsyncRpcResult.newDefaultAsyncResult(null, e, invocation);
            } else {
                throw e;
            }
        } catch (Throwable e) {
            asyncResult = AsyncRpcResult.newDefaultAsyncResult(null, e, invocation);
        }
        // 封装CompletableFuture 异步调用返回
        RpcContext.getContext().setFuture(new FutureAdapter(asyncResult.getResponseFuture()));
        return asyncResult;
}
protected abstract Result doInvoke(Invocation invocation) throws Throwable;

DubboInvoker.doInvoke

  @Override
    protected Result doInvoke(final Invocation invocation) throws Throwable {
        RpcInvocation inv = (RpcInvocation) invocation;
      	// 获取调用方法名
        final String methodName = RpcUtils.getMethodName(invocation);
        // 设置path和version到attachment中
        inv.setAttachment(PATH_KEY, getUrl().getPath());
        inv.setAttachment(VERSION_KEY, version);
        ExchangeClient currentClient;
        // 从clients数组中获取ExchangeClient
        if (clients.length == 1) {
            currentClient = clients[0];
        } else {
            currentClient = clients[index.getAndIncrement() % clients.length];
        }
        try {
        	// 获取异步配置 
            boolean isOneway = RpcUtils.isOneway(getUrl(), invocation);
           	// 获取超时数据 默认是 1s
            int timeout = getUrl().getMethodPositiveParameter(methodName, TIMEOUT_KEY, DEFAULT_TIMEOUT);
            // oneWay 为true 表示“单向"通信 没有返回值  kafka的消费发送方式  也有 oneWay
            if (isOneway) {
                boolean isSent = getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false);
                currentClient.send(inv, isSent); // 发送请求
                return AsyncRpcResult.newDefaultAsyncResult(invocation);
            } else { // 有返回值处理
                ExecutorService executor = getCallbackExecutor(getUrl(), inv);
                CompletableFuture<AppResponse> appResponseFuture =
                        currentClient.request(inv, timeout, executor).thenApply(obj -> (AppResponse) obj);
                // 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);
                return result;
            }
        } catch (TimeoutException e) {
            throw new RpcException(RpcException.TIMEOUT_EXCEPTION, "Invoke remote method timeout. method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);
        } catch (RemotingException e) {
            throw new RpcException(RpcException.NETWORK_EXCEPTION, "Failed to invoke remote method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);
        }
    }
	protected ExecutorService getCallbackExecutor(URL url, Invocation inv) {
        ExecutorService sharedExecutor = ExtensionLoader.getExtensionLoader(ExecutorRepository.class).getDefaultExtension().getExecutor(url);
        if (InvokeMode.SYNC == RpcUtils.getInvokeMode(getUrl(), inv)) {
            return new ThreadlessExecutor(sharedExecutor);
        } else {
            return sharedExecutor;
        }
    }

ExchangeClient

ReferenceCountExchangeClient(HeaderExchangeClient())
调用链路
ReferenceCountExchangeClient->HeaderExchangeClient->HeaderExchangeChannel->(request())
把构建好的RpcInvocation,组装到一个Request对象中进行传递

HeaderExchangeChannel#request()

 public CompletableFuture<Object> request(Object request, int timeout, ExecutorService executor) throws RemotingException {
        if (closed) {
            throw new RemotingException(this.getLocalAddress(), null, "Failed to send request " + request + ", cause: The channel " + this + " is closed!");
        }
        // 创建请求对象
        Request req = new Request();
        req.setVersion(Version.getProtocolVersion());
        req.setTwoWay(true);
        req.setData(request);
        DefaultFuture future = DefaultFuture.newFuture(channel, req, timeout, executor);
        try { 
            channel.send(req); // NettyClient
        } catch (RemotingException e) {
            future.cancel();
            throw e;
        }
        return future;
    }

channel.send(req)调用链路
AbstractPeer.send ->AbstractClient.send->NettyChannel.send
最终 通过NioSocketChannel把消息发送出去

 ChannelFuture future = channel.writeAndFlush(msg);

您可能感兴趣的与本文相关的镜像

Llama Factory

Llama Factory

模型微调
LLama-Factory

LLaMA Factory 是一个简单易用且高效的大型语言模型(Large Language Model)训练与微调平台。通过 LLaMA Factory,可以在无需编写任何代码的前提下,在本地完成上百种预训练模型的微调

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值