Dubbo源码分析(二):Dubbo之消费端(Consumer)

dubbo源码分析-consumer 发送与接收原理 1、consumer 发送扩展 我们先来看一下 dubbo 中 consumer 端的请求发送原理,也就是从 InvokerWrapper#invoke 开始,在 consumer 服务引用分析的时候,我们知道根据 Invoke 调用的时候, dubbo 会创建 ProtocolListenerWrapper与 ProtocolFilterWrapper 来用集成框架使用者的扩展包含:Invok... 阅读详情

    通观全部Dubbo代码,有两个很重要的对象就是Invoker和Exporter,Dubbo会根据用户配置的协议调用不同协议的Invoker,再通过ReferenceFonfig将Invoker的引用关联到Reference的ref属性上提供给消费端调用。当用户调用一个Service接口的一个方法后由于Dubbo使用javassist动态代理,会调用Invoker的Invoke方法从而初始化一个RPC调用访问请求访问服务端的Service返回结果。下面我们就从Comsumer端开始逐步解析这个框架。

    Dubbo首先使用com.alibaba.dubbo.config.spring.schema.NamespaceHandler注册解析器,当spring解析xml配置文件时就会调用这些解析器生成对应的BeanDefinition交给spring管理:

public class DubboNamespaceHandler extends NamespaceHandlerSupport {

	static {
		Version.checkDuplicate(DubboNamespaceHandler.class);
	}

	public void init() {
		//配置<dubbo:application>标签解析器
	    registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
        //配置<dubbo:module>标签解析器
	    registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
        //配置<dubbo:registry>标签解析器
	    registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
        //配置<dubbo:monitor>标签解析器
	    registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
        //配置<dubbo:provider>标签解析器
	    registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
        //配置<dubbo:consumer>标签解析器
	    registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
        //配置<dubbo:protocol>标签解析器
	    registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
	    //配置<dubbo:service>标签解析器
	    registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
	    //配置<dubbo:refenrence>标签解析器
	    registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
	    //配置<dubbo:annotation>标签解析器
	    registerBeanDefinitionParser("annotation", new DubboBeanDefinitionParser(AnnotationBean.class, true));
    }
}


    Spring在初始化IOC容器时会利用这里注册的BeanDefinitionParser的parse方法获取对应的ReferenceBean的BeanDefinition实例,由于ReferenceBean实现了InitializingBean接口,在设置了bean的所有属性后会调用afterPropertiesSet方法:

    public void afterPropertiesSet() throws Exception {
    	//如果Consumer还未注册
        if (getConsumer() == null) {
        	//获取applicationContext这个IOC容器实例中的所有ConsumerConfig
            Map<String, ConsumerConfig> consumerConfigMap = applicationContext == null ? null  : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ConsumerConfig.class, false, false);
            //如果IOC容器中存在这样的ConsumerConfig
            if (consumerConfigMap != null && consumerConfigMap.size() > 0) {
                ConsumerConfig consumerConfig = null;
                //遍历这些ConsumerConfig
                for (ConsumerConfig config : consumerConfigMap.values()) {
                	//如果用户没配置Consumer系统会生成一个默认Consumer,且它的isDefault返回ture
                	//这里是说要么是Consumer是默认的要么是用户配置的Consumer并且没设置isDefault属性
                    if (config.isDefault() == null || config.isDefault().booleanValue()) {
                    	//防止存在两个默认Consumer
                        if (consumerConfig != null) {
                            throw new IllegalStateException("Duplicate consumer configs: " + consumerConfig + " and " + config);
                        }
                        //获取默认Consumer
                        consumerConfig = config;
                    }
                }
                if (consumerConfig != null) {
                	//设置默认Consumer
                    setConsumer(consumerConfig);
                }
            }
        }
        //如果reference未绑定application且(reference未绑定consumer或referenc绑定的consumer没绑定application
        if (getApplication() == null
                && (getConsumer() == null || getConsumer().getApplication() == null)) {
        	//获取IOC中所有application的实例
            Map<String, ApplicationConfig> applicationConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class, false, false);
            if (applicationConfigMap != null && applicationConfigMap.size() > 0) {
            	//如果IOC中存在application
                ApplicationConfig applicationConfig = null;
                //遍历这些application
                for (ApplicationConfig config : applicationConfigMap.values()) {
                	//如果application是默认创建或者被指定成默认
                    if (config.isDefault() == null || config.isDefault().booleanValue()) {
                        if (applicationConfig != null) {
                            throw new IllegalStateException("Duplicate application configs: " + applicationConfig + " and " + config);
                        }
                        //获取application
                        applicationConfig = config;
                    }
                }
                if (applicationConfig != null) {
                	//关联到reference
                    setApplication(applicationConfig);
                }
            }
        }
        //如果reference未绑定module且(reference未绑定consumer或referenc绑定的consumer没绑定module
        if (getModule() == null
                && (getConsumer() == null || getConsumer().getModule() == null)) {
        	//获取IOC中所有module的实例
            Map<String, ModuleConfig> moduleConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class, false, false);
            if (moduleConfigMap != null && moduleConfigMap.size() > 0) {
                ModuleConfig moduleConfig = null;
              //遍历这些module
                for (ModuleConfig config : moduleConfigMap.values()) {
                	//如果module是默认创建或者被指定成默认
                    if (config.isDefault() == null || config.isDefault().booleanValue()) {
                        if (moduleConfig != null) {
                            throw new IllegalStateException("Duplicate module configs: " + moduleConfig + " and " + config);
                        }
                      //获取module
                        moduleConfig = config;
                    }
                }
                if (moduleConfig != null) {
                	//关联到reference
                    setModule(moduleConfig);
                }
            }
        }
        //如果reference未绑定注册中心(Register)且(reference未绑定consumer或referenc绑定的consumer没绑定注册中心(Register)
        if ((getRegistries() == null || getRegistries().size() == 0)
                && (getConsumer() == null || getConsumer().getRegistries() == null || getConsumer().getRegistries().size() == 0)
                && (getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().size() == 0)) {
        	//获取IOC中所有的注册中心(Register)实例
        	Map<String, RegistryConfig> registryConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class, false, false);
            if (registryConfigMap != null && registryConfigMap.size() > 0) {
                List<RegistryConfig> registryConfigs = new ArrayList<RegistryConfig>();
                //遍历这些registry
                for (RegistryConfig config : registryConfigMap.values()) {
                	//如果registry是默认创建或者被指定成默认
                    if (config.isDefault() == null || config.isDefault().booleanValue()) {
                        registryConfigs.add(config);
                    }
                }
                
                if (registryConfigs != null && registryConfigs.size() > 0) {
                	//关联到reference,此处可以看出一个consumer可以绑定多个registry(注册中心)
                    super.setRegistries(registryConfigs);
                }
            }
        }
      //如果reference未绑定监控中心(Monitor)且(reference未绑定consumer或reference绑定的consumer没绑定监控中心(Monitor)
        if (getMonitor() == null
                && (getConsumer() == null || getConsumer().getMonitor() == null)
                && (getApplication() == null || getApplication().getMonitor() == null)) {
        	//获取IOC中所有的监控中心(Monitor)实例
            Map<String, MonitorConfig> monitorConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class, false, false);
            if (monitorConfigMap != null && monitorConfigMap.size() > 0) {
                MonitorConfig monitorConfig = null;
                //遍历这些监控中心(Monitor)
                for (MonitorConfig config : monitorConfigMap.values()) {
                	//如果monitor是默认创建或者被指定成默认
                    if (config.isDefault() == null || config.isDefault().booleanValue()) {
                        if (monitorConfig != null) {
                            throw new IllegalStateException("Duplicate monitor configs: " + monitorConfig + " and " + config);
                        }
                        monitorConfig = config;
                    }
                }
                if (monitorConfig != null) {
                	//关联到reference,一个consumer绑定到一个监控中心(monitor)
                    setMonitor(monitorConfig);
                }
            }
        }
        Boolean b = isInit();
        if (b == null && getConsumer() != null) {
            b = getConsumer().isInit();
        }
        if (b != null && b.booleanValue()) {
        	//如果consumer已经被关联则组装Reference
            getObject();
        }
    }
}

      这步其实是Reference确认生成Invoker所需要的组件是否已经准备好,都准备好后我们进入生成Invoker的部分。这里的getObject会调用父类ReferenceConfig的init方法完成组装:

     

private void init() {
    	//避免重复初始化
	    if (initialized) {
	        return;
	    }
	    //置为已经初始化
	    initialized = true;
	    //如果interfaceName不存在
    	if (interfaceName == null || interfaceName.length() == 0) {
    	    throw new IllegalStateException("<dubbo:reference interface=\"\" /> interface not allow null!");
    	}
    	// 获取消费者
    	checkDefault();
        appendProperties(this);
        //如果未使用泛接口并且consumer已经准备好的情况下,reference使用和consumer一样的泛接口
        if (getGeneric() == null && getConsumer() != null) {
            setGeneric(getConsumer().getGeneric());
        }
        //如果是泛接口那么interface的类型是GenericService
        if (ProtocolUtils.isGeneric(getGeneric())) {
            interfaceClass = GenericService.class;
        } else {
        	//如果不是泛接口使用interfaceName指定的泛接口
            try {
				interfaceClass = Class.forName(interfaceName, true, Thread.currentThread()
				        .getContextClassLoader());
			} catch (ClassNotFoundException e) {
				throw new IllegalStateException(e.getMessage(), e);
			}
            //检查接口以及接口中的方法都是否配置齐全
            checkInterfaceAndMethods(interfaceClass, methods);
        }
        //如果服务比较多可以指定dubbo-resolve.properties文件配置service(service集中配置文件)
        String resolve = System.getProperty(interfaceName);
        String resolveFile = null;
        if (resolve == null || resolve.length() == 0) {
	        resolveFile = System.getProperty("dubbo.resolve.file");
	        if (resolveFile == null || resolveFile.length() == 0) {
	        	File userResolveFile = new File(new File(System.getProperty("user.home")), "dubbo-resolve.properties");
	        	if (userResolveFile.exists()) {
	        		resolveFile = userResolveFile.getAbsolutePath();
	        	}
	        }
	        if (resolveFile != null && resolveFile.length() > 0) {
	        	Properties properties = new Properties();
	        	FileInputStream fis = null;
	        	try {
	        	    fis = new FileInputStream(new File(resolveFile));
					properties.load(fis);
				} catch (IOException e) {
					throw new IllegalStateException("Unload " + resolveFile + ", cause: " + e.getMessage(), e);
				} finally {
				    try {
                        if(null != fis) fis.close();
                    } catch (IOException e) {
                        logger.warn(e.getMessage(), e);
                    }
				}
	        	resolve = properties.getProperty(interfaceName);
	        }
        }
        if (resolve != null && resolve.length() > 0) {
        	url = resolve;
        	if (logger.isWarnEnabled()) {
        		if (resolveFile != null && resolveFile.length() > 0) {
        			logger.warn("Using default dubbo resolve file " + resolveFile + " replace " + interfaceName + "" + resolve + " to p2p invoke remote service.");
        		} else {
        			logger.warn("Using -D" + interfaceName + "=" + resolve + " to p2p invoke remote service.");
        		}
    		}
        }
        //如果application、module、registries、monitor未配置则使用consumer的
        if (consumer != null) {
            if (application == null) {
                application = consumer.getApplication();
            }
            if (module == null) {
                module = consumer.getModule();
            }
            if (registries == null) {
                registries = consumer.getRegistries();
            }
            if (monitor == null) {
                monitor = consumer.getMonitor();
            }
        }
        //如果module已关联则关联module的registries和monitor
        if (module != null) {
            if (registries == null) {
                registries = module.getRegistries();
            }
            if (monitor == null) {
                monitor = module.getMonitor();
            }
        }
      //如果application已关联则关联application的registries和monitor
        if (application != null) {
            if (registries == null) {
                registries = application.getRegistries();
            }
            if (monitor == null) {
                monitor = application.getMonitor();
            }
        }
        //检查application
        checkApplication();
        //检查远端和本地服务接口真实存在(是否可load)
        checkStubAndMock(interfaceClass);
        Map<String, String> map = new HashMap<String, String>();
        //配置dubbo的端属性(是consumer还是provider)、版本属性、创建时间、进程号
        Map<Object, Object> attributes = new HashMap<Object, Object>();
        map.put(Constants.SIDE_KEY, Constants.CONSUMER_SIDE);
        map.put(Constants.DUBBO_VERSION_KEY, Version.getVersion());
        map.put(Constants.TIMESTAMP_KEY, String.valueOf(System.currentTimeMillis()));
        if (ConfigUtils.getPid() > 0) {
            map.put(Constants.PID_KEY, String.valueOf(ConfigUtils.getPid()));
        }
        if (! isGeneric()) {
            String revision = Version.getVersion(interfaceClass, version);
            if (revision != null && revision.length() > 0) {
                map.put("revision", revision);
            }

            String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames();
            if(methods.length == 0) {
                logger.warn("NO method found in service interface " + interfaceClass.getName());
                map.put("methods", Constants.ANY_VALUE);
            }
            else {
                map.put("methods", StringUtils.join(new HashSet<String>(Arrays.asList(methods)), ","));
            }
        }
        map.put(Constants.INTERFACE_KEY, interfaceName);
        //调用application、module、consumer的get方法将属性设置到map中
        appendParameters(map, application);
        appendParameters(map, module);
        appendParameters(map, consumer, Constants.DEFAULT_KEY);
        appendParameters(map, this);
        String prifix = StringUtils.getServiceKey(map);
        if (methods != null && methods.size() > 0) {
            for (MethodConfig method : methods) {
                appendParameters(map, method, method.getName());
                String retryKey = method.getName() + ".retry";
                if (map.containsKey(retryKey)) {
                    String retryValue = map.remove(retryKey);
                    if ("false".equals(retryValue)) {
                        map.put(method.getName() + ".retries", "0");
                    }
                }
                appendAttributes(attributes, method, prifix + "." + method.getName());
                checkAndConvertImplicitConfig(method, map, attributes);
            }
        }
        //attributes通过系统context进行存储.
        StaticContext.getSystemContext().putAll(attributes);
        //在map装载了application、module、consumer、reference的所有属性信息后创建代理
        ref = createProxy(map);
    }


private T createProxy(Map<String, String> map) {
		URL tmpUrl = new URL("temp", "localhost", 0, map);
		final boolean isJvmRefer;
        if (isInjvm() == null) {
            if (url != null && url.length() > 0) { //指定URL的情况下,不做本地引用
                isJvmRefer = false;
            } else if (InjvmProtocol.getInjvmProtocol().isInjvmRefer(tmpUrl)) {
                //默认情况下如果本地有服务暴露,则引用本地服务.
                isJvmRefer = true;
            } else {
                isJvmRefer = false;
            }
        } else {
            isJvmRefer = isInjvm().booleanValue();
        }
		
		if (isJvmRefer) {
			URL url = new URL(Constants.LOCAL_PROTOCOL, NetUtils.LOCALHOST, 0, interfaceClass.getName()).addParameters(map);
			invoker = refprotocol.refer(interfaceClass, url);
            if (logger.isInfoEnabled()) {
                logger.info("Using injvm service " + interfaceClass.getName());
            }
		} else {
            if (url != null && url.length() > 0) { // 用户指定URL,指定的URL可能是对点对直连地址,也可能是注册中心URL
                String[] us = Constants.SEMICOLON_SPLIT_PATTERN.split(url);
                if (us != null && us.length > 0) {
                    for (String u : us) {
                        URL url = URL.valueOf(u);
                        if (url.getPath() == null || url.getPath().length() == 0) {
                            url = url.setPath(interfaceName);
                        }
                        if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
                            urls.add(url.addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map)));
                        } else {
                            urls.add(ClusterUtils.mergeUrl(url, map));
                        }
                    }
                }
            } else { // 通过注册中心配置拼装URL
            	List<URL> us = loadRegistries(false);
            	if (us != null && us.size() > 0) {
                	for (URL u : us) {
                	    URL monitorUrl = loadMonitor(u);
                        if (monitorUrl != null) {
                            map.put(Constants.MONITOR_KEY, URL.encode(monitorUrl.toFullString()));
                        }
                	    urls.add(u.addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map)));
                    }
            	}
            	if (urls == null || urls.size() == 0) {
                    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.");
                }
            }

            if (urls.size() == 1) {
            	//此处举例说明如果是Dubbo协议则调用DubboProtocol的refer方法生成invoker,当用户调用service接口实际调用的是invoker的invoke方法
                invoker = refprotocol.refer(interfaceClass, urls.get(0));
            } else {
            	//多个service生成多个invoker
                List<Invoker<?>> invokers = new ArrayList<Invoker<?>>();
                URL registryURL = null;
                for (URL url : urls) {
                    invokers.add(refprotocol.refer(interfaceClass, url));
                    if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
                        registryURL = url; // 用了最后一个registry url
                    }
                }
                if (registryURL != null) { // 有 注册中心协议的URL
                    // 对有注册中心的Cluster 只用 AvailableCluster
                    URL u = registryURL.addParameter(Constants.CLUSTER_KEY, AvailableCluster.NAME); 
                    invoker = cluster.join(new StaticDirectory(u, invokers));
                }  else { // 不是 注册中心的URL
                    invoker = cluster.join(new StaticDirectory(invokers));
                }
            }
        }

        Boolean c = check;
        if (c == null && consumer != null) {
            c = consumer.isCheck();
        }
        if (c == null) {
            c = true; // default true
        }
        if (c && ! 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());
        }
        // 创建服务代理
        return (T) proxyFactory.getProxy(invoker);
    }


      至此Reference在关联了所有application、module、consumer、registry、monitor、service、protocol后调用对应Protocol类的refer方法生成InvokerProxy。当用户调用service时dubbo会通过InvokerProxy调用Invoker的invoke的方法向服务端发起请求。客户端就这样完成了自己的初始化。




dubbo 消费者(consumer)线程模型及2.7.1版本问题 背景 2.7.1的dubbo,默认情况下,消费者在接收返回消息时,会将消息指定到all的Dispatcher中,然后将消息丢入线程池等待调度处理,消费者接收消息使用的线程池默认是cached(缓存线程池),此时会存在两个问题: 线程池创建过多; 线程池线程数无限制; 第一个问题是因为dubbo的线程模型中,线程池的个数与客户端引用的服务个数,服务提供者的数量,connections都有关,总的来说消费者与提供者建立一条连接,则消费者创建一个线程池处理返回消息,即: 消费方线程池个数 = Reference服 阅读详情

相关推荐

电源设计避坑指南:半桥LLC软启动的5个常见错误及解决方案

本文针对半桥LLC谐振变换器软启动过程中的五个常见设计错误,提供了详细的工程解决方案。重点分析了忽视谐振腔初始状态导致的电流冲击、软启动斜坡与环路带宽不匹配、开环到闭环切换时机不当、变压器偏磁以及参数未考虑边界条件等问题,并给出了包括主动预充电、自适应斜坡、最佳切换点判定等实用调试技巧,帮助工程师实现平稳可靠的电源启动。

weixin_29260291的博客 278

Dubbo服务引用

引言 前面的文章中,我们已经详细介绍了服务暴露的相关细节,本文中,我们主要深入介绍服务引用的实现细节。 引用服务方式 在 Dubbo 中,我们可以通过两种方式引用远程服务。第一种是使用服务直连的方式引用服务,第二种方式是基于注册中心进行引用。服务直连的方式仅适合在调试或测试服务的场景下使用,不适合在线上环境使用。因此,接下来我将重点分析通过注册中心引用服务的过程。从注册中心中获取服务配置只是服务引用过程中的一环,除此之外,服务消费者还需要经历 Invoker 创建、代理类创建等步骤。 Dubbo 服务引用的

贝克街的流浪猫 422

2022年TI杯模拟电⼦系统设计专题邀请赛——李萨如图形演示装置

本次装置主要是对输入的正弦信号进行频率变换,并将原输入正弦信号作为 X 轴信号、变换后的正弦信号作为 Y 轴信号,绘制李萨如图形。采用 EK-TM4C123GXL 板卡作为主控;频率变换采用“锁向环+计数器”实现 1-5 倍频的频率变换控制;李萨如图形采用两个 AD通道采集原输入的正弦信号作为 X 轴信号和频率变换后的正弦信号作为 Y 轴信号,绘制李萨如图形。

qq_45890466的博客 7768

Dubbo入门(三)Consumer的编写

前言 本章讲解dubbo中另外一个重要角色Consumer的编写 方法 1.概念 既然我们在上个章节创建了dubbo的服务提供者provider,那么必然是要有消费者进行消费的。 本章将根据dubbo流程图进一步探寻。 consumer可以是java工程也可以是web工程,本次使用java工程进行讲解。 2.编写步骤 1)新建maven的jar工程 2)编写...

jwang的博客 2129

SFF-8654接口引脚定义全解析:从SAS到U.2的高速硬件连接核心

在高速数据存储与传输领域,接口标准是连接主机与存储设备、确保信号完整性与协议互通性的物理基础。其核心原理在于通过精确定义的物理引脚和电气特性,承载不同的高速串行通信协议,如SAS和PCIe。这类高密度连接器的技术价值在于以紧凑的形态支持多协议兼容与高速率传输,满足了企业级存储、高性能计算对带宽和可靠性的苛刻要求。典型的应用场景包括服务器硬盘背板连接、NVMe U.2固态硬盘直连以及外部存储扩展。本文聚焦于SFF-8654(亦称Mini SAS HD)这一关键接口,深入剖析其引脚定义、信号分区(如高速数据通道

weixin_29188043的博客 710

对西安交大轴承数据集XJTU-SY_Bearing_Datasets进行读取和处理:

故障诊断,对西安交大轴承数据集XJTU-SY_Bearing_Datasets进行读取和处理

qq_44757503的博客 6060

Dubbo源码解读-Consumer调用流程解析

消费端依赖代理对象,代理调用的入口为MockClusterInvoker.invoke持有集群容错类Cluster,默认FailOverCluster。MockClusterInvoker实现了Mock调用的原理从Url上获取配置的mock信息如果没有mock走远程RPC。获取服务列表(订阅事件,服务列表本地缓存)获取负载均衡算法。抽象类AbstractClusterInvoker调用子类具体集群容错类的doInvoke(),实现远程服务调用。调用负载均衡算法选择一个Invoker.

胖墩儿没腹肌 2766

获取本机正版windows10激活密钥,以及正版office

本方法面向的是以前买过笔记本电脑给你预装了正版系统,激活了正版office(一般是家庭版)的情况,其他情况请自行尝试。

qq_45774917的博客 2万+

dubbo之服务消费者配置

1:写在前面 在这篇文章 中我们分析了服务提供者配置的相关源码,本文一起来看下服务消费者配置相关的源码,还是看一个通过API 方式配置服务消费者的实例代码: public class ConsumerWithApiConfigMain { public static void main(String[] args) { // 当前应用配置 ApplicationConfig application = new ApplicationConfig();

wang0907的博客 3967

极智嘉嵌入式面试题及参考答案

IIC(Inter-Integrated Circuit)即集成电路总线,是一种由 PHILIPS 公司开发的两线式串行总线,用于连接微控制器及其外围设备。它仅使用两根线,即串行数据线 SDA 和串行时钟线 SCL,就能实现多个设备之间的通信,具有简单、高效、占用资源少等优点,广泛应用于各种嵌入式系统中。

大模型大数据攻城狮的专栏 921

第42章:AI代码生成的质量标准——何时用AI、何时自己写

> - AI代码生成的质量分级标准:可用、稳定、安全、优雅 > - 一个决策矩阵:什么场景适合用AI,什么场景必须人工编写 > - 如何评估AI生成的代码质量(复杂度、可读性、安全性) > - 实战对比:同一需求下AI生成代码 vs 人工编写代码 > - 团队落地:将质量标准集成到Code Review和CI流程 > - 我如何将团队AI代码接受率从70%提升到90%

sfishfly的博客 161

dubbo源码分析-consumer端5-Filter

前面一篇dubbo源码分析中,我们对ClusterInvoker和LoadBalance进行了分析,可以知道ClusterInvoker在一批Invoker中选择了一个Invoker来进行调用,而这里的Invoker是通过RegistryDirectory得到的,而RegistryDirectory返回的Invoker实现为:InvokerDelegete(RegistryDirectory的内部

youaremoon的专栏 5881

【ROS】Nav2源码之nav2_collision_monitor(碰撞监测)详解

nav2_collision_monitor碰撞监视器是一个节点,为机器人提供了一个额外的安全级别。它使用来自传感器的数据,执行若干与避免碰撞相关的任务,绕过成本图和轨迹规划器,监测是否需要紧急停止或者减速。

郭老二 1455

dubbo源码分析-consumer端1-consumer代理生成

主要介绍dubbo的consumer代理类生成流程

youaremoon的专栏 5891

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

dubbo源码分析-consumer端3-Invoker创建流程

从前面一篇创建注册中心的流程当中,我们知道在从注册中心获取到provider的连接信息后,会通过连接创建Invoker。代码见com.alibaba.dubbo.registry.integration.RegistryDirectory的toInvokers方法: // protocol实现为com.alibaba.dubbo.rpc.Protocol$Adpative, // 之前

youaremoon的专栏 5776

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Dubbo源码分析之消费端

dubbo的xml配置文件<dubbo:reference>对应的就是ReferenceBean,它实现了FactoryBean,所以在初始化实例时就会调用他的实现方法,从而开启服务引用 public Object getObject() { return get(); } 检查必要的配置信息,加载注册中心URL,拼装引用URL。 checkRegistry(); ...

587

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

dubbo源码分析之consumer端调用原理-22

在前面的文章中,我们分析了 dubbo 从 provider 进行服务暴露,然后把服务信息注册到注册中心上面解耦 consumer 与 provider 的调用。consumer 通过 javassist 创建代理对象引用远程服务。当通过代理对象调用远程服务的时候,讲到进行真正调用的时候 dubbo 抽象出集群容错(Cluster、Directory、Router、LoadBalance)从服务多...

Jack博客 803

dubbo源码分析-consumer端4-MockClusterInvoker

在前面几篇文章中,我们分析了consumer端的代理生成过程。创建完成后,应用就可以进行调用了,调用的代码如下: // 代理类中的sayHello方法 public String sayHello(String paramString) { // 将调用时的参数传入arrayOfObject中 Object[] arrayOfObject = new Object

youaremoon的专栏 3551

Dubbo 源码分析04 服务消费端consumer 启动流程

入口是ReferenceBean#afterPropertiesSet  Step1:如果consumer为空,说明dubbo:reference标签未设置consumer属性,如果一个dubbo:consumer标签,则取该实例,如果存在多个dubbo:consumer 配置,则consumer必须设置,否则会抛出异常:“Duplicate consumer configs”。   Step...

郭传志的博客 316

dubbo源码分析-consumer端4-ClusterInvoker与LoadBalance

dubbo中提供了多种集群调用策略:         1、FailbackClusterInvoker :  失败自动恢复,后台记录失败请求,定时重发,通常用于消息通知操作;         2、FailfastClusterInvoker: 快速失败,只发起一次调用,失败立即报错,通常用于非幂等性的写操作;         3、FailoverClusterInvoker: 失败转移,当出

youaremoon的专栏 7156

dubbo源码之消费端启动和调用

1.依次调用AbstractApplicationContext#getBean()->FactoryBeanRegistrySupport#doGetObjectFromFactoryBean->ReferenceBean#getObject->ReferenceConfig#init,代码如下图:方法逻辑和服务端导出服务类似.3.从AbstractClusterInvoker#invoke方法依次调用FailoverClusterInvoker#doInvoke,代码如下图,

研究源码的最底层,只持有正确的仓位 565

dubbo源码分析-consumer端2-创建注册中心

前面一篇文章我们分析了consumer代理的生成。在代理生成的过程中,会创建注册服务(com.alibaba.dubbo.registry.Registry)。通过注册服务提供url注册、订阅、查找的功能。本篇我们详细的看看注册中心的创建过程

youaremoon的专栏 4287

dubbo protocol port 消费者端_Dubbo架构设计

Dubbo架构设计Dubbo调用关系主要由四个部分组成:Provider:暴露服务的服务提供方protocol:负责提供者和消费者之间协议交互数据Service:真实的业务服务信息,可以理解成接口和实现Container:Dubbo的运行环境Consumer:调用服务的服务消费方Protocol:负责提供者和消费者之间的协议交互数据Cluster:感知提供者端的列表信息Proxy:可以理解成提供者...

weixin_36028243的博客 1383
上一篇: Dubbo源码分析(一):概览
下一篇: Dubbo源码分析(三):Dubbo之服务端(Service)
闲庭细步
博客等级 码龄18年 304粉丝 86原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值