Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >dubbo源码——服务提供者的服务暴露过程(一)

dubbo源码——服务提供者的服务暴露过程(一)

原创
作者头像
冰枫
修改于 2018-06-10 09:32:15
修改于 2018-06-10 09:32:15
2.7K00
代码可运行
举报
文章被收录于专栏:冰枫冰枫
运行总次数:0
代码可运行

一、前言

最近在学习dubbo源码,故写下学习dubbo时的一些心得。。

dubbo源码版本:2.6.1

二、自定义标签

<dubbo:xxx/>标签是Spring的自定义标签,可以查看dubbo.jar包下的META-INF->spring.handlers

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//file:spring.handlers
http\://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler

它是通过DubboNamespaceHandler继承Spring提供的NamespaceHandlerSupport来对标签进行解析的

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//DubboNamespaceHandler.java
public class DubboNamespaceHandler extends NamespaceHandlerSupport {

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

    public void init() {
        registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
        registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
        registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
        registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
        registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
        registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
        registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
        registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
        registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
        registerBeanDefinitionParser("annotation", new AnnotationBeanDefinitionParser());
    }

}

本篇博客主要讲解的是服务提供者的服务暴露过程,也就是<dubbo:service/>标签,那么我们就只需要关心newDubboBeanDefinitionParser(ServiceBean.class,true),ServiceBean的实现即可。

三、ServiceBean

先附上一张ServiceBean架构图。可以看到ServiceBean实现了一系列的Spring生命周期接口来完成服务的暴露、注册、销毁等操作。

我们暂不必关心其它接口的实现,我们更关心的是InitializingBean的实现,因为它包含了我们所要研究的服务提供者暴露过程。

哇哦,这代码还真tm长啊,一会还有更长的.....

  • #1:获取<dubbo:service />的provider属性,如果为空,那么就获取<dubbo:provider/>的实例。(dubbo:provider标签配置的是一些缺省值)

①如果没有配置<dubbo:protocol/>协议,并且,<dubbo:provider/>配置了一个以上,那么会选择provider标签配置了default属性的ProviderConfig

②如果配置了<dubbo:protocol/>协议,如果<dubbo:provider/>配置了一个以上那么会报Duplicate provider configs:异常,否则将会选择一个ProviderConfig。

  • #2获取application属性,如果属性为空,且provider也为空;或者属性为空,provider中application也为空,那么会获取<dubbo:application/>的实例,如果配置了多个<dubbo:application/>标签,则会抛出异常Duplicate application configs:
  • #3获取module属性,和application一样,如果属性为空,且provider也为空;或者属性为空,provider中module也为空那么会获取<dubbo:module/>的实例,如果配置了多个<dubbo:module/>标签,则会抛出异常Duplicate module configs:
  • #4获取registries属性,如果为空,则获取provider中的registries属性,如果也为空,则获取application中的registries属性,如果还为空,那么就去找<dubbo:registry/>标签的实例,dubbo允许配置多个注册中心,将服务注册在不同的注册中心上。
  • #5获取monitor属性,如果为空,则尝试从provider、application中获取,否则,会获取<dubbo:monitor/>标签的实例,monitor可有可无,不过只能配置一个,存在多个会抛出异常Duplicate monitor configs:
  • #6获取protocol属性,如果为空,则获取provider中protocol属性,如果为空,则会获取<dubbo:protocol/>标签的实例,protocol可配置多个,dubbo允许将服务通过不同协议进行暴露。
  • #7延时暴露,如果delay没有设置,或者delay设置为-1将会启用延时加载。是通过实现ApplicationListener接口在SpringIOC初始化完毕后通知ServiceBean完成服务暴露回调,schedule定时任务(单位毫秒)。来实现的。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private boolean isDelay() {
        Integer delay = getDelay();
        ProviderConfig provider = getProvider();
        if (delay == null && provider != null) {
            delay = provider.getDelay();
        }
        return supportedApplicationListener && (delay == null || delay == -1);
    }
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 public void onApplicationEvent(ContextRefreshedEvent event) {
        if (isDelay() && !isExported() && !isUnexported()) {
            if (logger.isInfoEnabled()) {
                logger.info("The service ready on spring started. service: " + getInterface());
            }
            export();
        }
    }

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//ServiceBean->afterPropertiesSet()
    @SuppressWarnings({"unchecked", "deprecation"})
    public void afterPropertiesSet() throws Exception {
        if (getProvider() == null) { #1
            Map<String, ProviderConfig> providerConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class, false, false);
            if (providerConfigMap != null && providerConfigMap.size() > 0) {
                Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false);
                if ((protocolConfigMap == null || protocolConfigMap.size() == 0)
                        && providerConfigMap.size() > 1) { // backward compatibility
                    List<ProviderConfig> providerConfigs = new ArrayList<ProviderConfig>();
                    for (ProviderConfig config : providerConfigMap.values()) {
                        if (config.isDefault() != null && config.isDefault().booleanValue()) {
                            providerConfigs.add(config);
                        }
                    }
                    if (!providerConfigs.isEmpty()) {
                        setProviders(providerConfigs);
                    }
                } else {
                    ProviderConfig providerConfig = null;
                    for (ProviderConfig config : providerConfigMap.values()) {
                        if (config.isDefault() == null || config.isDefault().booleanValue()) {
                            if (providerConfig != null) {
                                throw new IllegalStateException("Duplicate provider configs: " + providerConfig + " and " + config);
                            }
                            providerConfig = config;
                        }
                    }
                    if (providerConfig != null) {
                        setProvider(providerConfig);
                    }
                }
            }
        }
        if (getApplication() == null   #2
                && (getProvider() == null || getProvider().getApplication() == null)) {
            Map<String, ApplicationConfig> applicationConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class, false, false);
            if (applicationConfigMap != null && applicationConfigMap.size() > 0) {
                ApplicationConfig applicationConfig = null;
                for (ApplicationConfig config : applicationConfigMap.values()) {
                    if (config.isDefault() == null || config.isDefault().booleanValue()) {
                        if (applicationConfig != null) {
                            throw new IllegalStateException("Duplicate application configs: " + applicationConfig + " and " + config);
                        }
                        applicationConfig = config;
                    }
                }
                if (applicationConfig != null) {
                    setApplication(applicationConfig);
                }
            }
        }
        if (getModule() == null     #3
                && (getProvider() == null || getProvider().getModule() == null)) {
            Map<String, ModuleConfig> moduleConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class, false, false);
            if (moduleConfigMap != null && moduleConfigMap.size() > 0) {
                ModuleConfig moduleConfig = null;
                for (ModuleConfig config : moduleConfigMap.values()) {
                    if (config.isDefault() == null || config.isDefault().booleanValue()) {
                        if (moduleConfig != null) {
                            throw new IllegalStateException("Duplicate module configs: " + moduleConfig + " and " + config);
                        }
                        moduleConfig = config;
                    }
                }
                if (moduleConfig != null) {
                    setModule(moduleConfig);
                }
            }
        }
        if ((getRegistries() == null || getRegistries().isEmpty())  #4
                && (getProvider() == null || getProvider().getRegistries() == null || getProvider().getRegistries().isEmpty())
                && (getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().isEmpty())) {
            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>();
                for (RegistryConfig config : registryConfigMap.values()) {
                    if (config.isDefault() == null || config.isDefault().booleanValue()) {
                        registryConfigs.add(config);
                    }
                }
                if (registryConfigs != null && !registryConfigs.isEmpty()) {
                    super.setRegistries(registryConfigs);
                }
            }
        }
        if (getMonitor() == null    #5
                && (getProvider() == null || getProvider().getMonitor() == null)
                && (getApplication() == null || getApplication().getMonitor() == null)) {
            Map<String, MonitorConfig> monitorConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class, false, false);
            if (monitorConfigMap != null && monitorConfigMap.size() > 0) {
                MonitorConfig monitorConfig = null;
                for (MonitorConfig config : monitorConfigMap.values()) {
                    if (config.isDefault() == null || config.isDefault().booleanValue()) {
                        if (monitorConfig != null) {
                            throw new IllegalStateException("Duplicate monitor configs: " + monitorConfig + " and " + config);
                        }
                        monitorConfig = config;
                    }
                }
                if (monitorConfig != null) {
                    setMonitor(monitorConfig);
                }
            }
        }
        if ((getProtocols() == null || getProtocols().isEmpty()) #6
                && (getProvider() == null || getProvider().getProtocols() == null || getProvider().getProtocols().isEmpty())) {
            Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false);
            if (protocolConfigMap != null && protocolConfigMap.size() > 0) {
                List<ProtocolConfig> protocolConfigs = new ArrayList<ProtocolConfig>();
                for (ProtocolConfig config : protocolConfigMap.values()) {
                    if (config.isDefault() == null || config.isDefault().booleanValue()) {
                        protocolConfigs.add(config);
                    }
                }
                if (protocolConfigs != null && !protocolConfigs.isEmpty()) {
                    super.setProtocols(protocolConfigs);
                }
            }
        }
        if (getPath() == null || getPath().length() == 0) {
            if (beanName != null && beanName.length() > 0
                    && getInterface() != null && getInterface().length() > 0
                    && beanName.startsWith(getInterface())) {
                setPath(beanName);
            }
        }
        if (!isDelay()) {     #7
            export();
        }
    }

接下来分析export()服务暴露方法

  • #1#2如果没有配置export属性和delay属性,则从provider中获取。
  • #3如果export属性为false,那么将不暴露服务,直接返回。
  • #4如果delay不为空 且大于0,将定时执行服务暴露任务。否则直接执行。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//ServiceConfig.java
//ServiceCofnig->export()
public synchronized void export() {
        if (provider != null) {    #1
            if (export == null) {
                export = provider.getExport();
            }
            if (delay == null) {   #2
                delay = provider.getDelay();
            }
        }
        if (export != null && !export) { #3
            return;
        }

        if (delay != null && delay > 0) { #4
            delayExportExecutor.schedule(new Runnable() {
                public void run() {
                    doExport();
                }
            }, delay, TimeUnit.MILLISECONDS);
        } else {
            doExport();
        }
    }

好吧,doExport()方法依然很长。。。

  • #1如果服务已经暴露,则直接返回。
  • #2<dubbo:service/>中interface配置为空,则抛出异常。
  • #3从参数,或者系统文件中加载属性配置
  • #4前面都是一些属性的填充,很无聊,直接跳过,如果服务ref为genericService或者其子类,那么将会获取generic属性,默认为true。
  • #5否则为普通的接口,加载接口,然后接口方法检查,引用与接口是否匹配。
  • #6stub属性为true,那么会查找接口的Stub类,Stub可以查看这篇博客https://www.cnblogs.com/hzhuxin/p/8250602.html
  • #7进行一系列的属性检查和填充。
  • #8path默认为接口名称例如:dubbo://127.0.0.1:28080/interfaceName.....
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//ServiceConfig.java 
//ServiceConfig->doExport()

 protected synchronized void doExport() {
        if (unexported) {
            throw new IllegalStateException("Already unexported!");
        }
        if (exported) {  #1
            return;
        }
        exported = true;
        if (interfaceName == null || interfaceName.length() == 0) { #2
            throw new IllegalStateException("<dubbo:service interface=\"\" /> interface not allow null!");
        }
        checkDefault();  #3
        if (provider != null) {
            if (application == null) {
                application = provider.getApplication();
            }
            if (module == null) {
                module = provider.getModule();
            }
            if (registries == null) {
                registries = provider.getRegistries();
            }
            if (monitor == null) {
                monitor = provider.getMonitor();
            }
            if (protocols == null) {
                protocols = provider.getProtocols();
            }
        }
        if (module != null) {
            if (registries == null) {
                registries = module.getRegistries();
            }
            if (monitor == null) {
                monitor = module.getMonitor();
            }
        }
        if (application != null) {
            if (registries == null) {
                registries = application.getRegistries();
            }
            if (monitor == null) {
                monitor = application.getMonitor();
            }
        }
        if (ref instanceof GenericService) { #4
            interfaceClass = GenericService.class;
            if (StringUtils.isEmpty(generic)) {
                generic = Boolean.TRUE.toString();
            }
        } else {
            try {   #5
                interfaceClass = Class.forName(interfaceName, true, Thread.currentThread()
                        .getContextClassLoader());
            } catch (ClassNotFoundException e) {
                throw new IllegalStateException(e.getMessage(), e);
            }
            checkInterfaceAndMethods(interfaceClass, methods);
            checkRef();
            generic = Boolean.FALSE.toString();
        }
        if (local != null) {
            if ("true".equals(local)) {
                local = interfaceName + "Local";
            }
            Class<?> localClass;
            try {
                localClass = ClassHelper.forNameWithThreadContextClassLoader(local);
            } catch (ClassNotFoundException e) {
                throw new IllegalStateException(e.getMessage(), e);
            }
            if (!interfaceClass.isAssignableFrom(localClass)) {
                throw new IllegalStateException("The local implementation class " + localClass.getName() + " not implement interface " + interfaceName);
            }
        }
        if (stub != null) {   #6
            if ("true".equals(stub)) {
                stub = interfaceName + "Stub";
            }
            Class<?> stubClass;
            try {
                stubClass = ClassHelper.forNameWithThreadContextClassLoader(stub);
            } catch (ClassNotFoundException e) {
                throw new IllegalStateException(e.getMessage(), e);
            }
            if (!interfaceClass.isAssignableFrom(stubClass)) {
                throw new IllegalStateException("The stub implementation class " + stubClass.getName() + " not implement interface " + interfaceName);
            }
        }
        checkApplication();  #7
        checkRegistry();
        checkProtocol();
        appendProperties(this);
        checkStubAndMock(interfaceClass);
        if (path == null || path.length() == 0) { #8
            path = interfaceName;
        }
        doExportUrls();
        ProviderModel providerModel = new ProviderModel(getUniqueServiceName(), this, ref);
        ApplicationModel.initProviderModel(getUniqueServiceName(), providerModel);
    }
    

锵锵锵,该doExportUrls()方法了,眼睛酸,下篇博客讲!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
dubbo基于spring运行原理解析
dubbo是基于spring构建和运行的,兼容spring配置。这篇说说dubbo基于spring的过程。 dubbo首先利用了从spring2.0开始的一个特性,Extensible XML authoring,扩展spring了标签功能。 关于如何利用spring扩展自己的标签,可以参考下官方介绍 https://docs.spring.io/spring/docs/3.2.18.RELEASE/spring-framework-reference/htmlsingle/#extensible-xml 根据文档的说法,需要如下4步: 1,编写xml,描述需要扩展的标签的配置属性,dubbo实现放在jar包META-INF/dubbo.xsd文件里 同时通过编写META-INF/spring.handlers文件,提供给spring,内容如下 http\://code.alibabatech.com/schema/dubbo/dubbo.xsd=META-INF/dubbo.xsd xsd文件也很好编写阅读,里面有继承和嵌套的概念。 2,写一个NamespaceHandler接口实现类,dubbo的实现类是DubboNamespaceHandler 同时通过编写META-INF/spring.schemas文件,提供给spring,内容如下: http\://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler 3,编写一个(或者多个)BeanDefinitionParser实现类,用来解析扩展的元素,dubbo实现类是DubboBeanDefinitionParser, 这个类也是真正的需要自己处理的代码所在。 4,把以上组件注册给spirng,这个dubbo其实在DubboNamespaceHandler类里。
技术蓝海
2018/04/26
2K0
dubbo基于spring运行原理解析
dubbo源码分析之filter加载机制
1. dubbo xml格式加载机制 1. xml中的配置: <dubbo:provider filter="MDCFilter,DubboExceptionFilter,-exception" delay="-1" timeout="7000" retries="0" /> 2. 加载入口 public class DubboNamespaceHandler extends NamespaceHandlerSupport { static { Version.checkDuplicate(Dubb
山行AI
2019/06/28
1.2K0
Dubbo2.7源码详解
    1)DubboConfigConfigurationRegistrar类的作用
忧愁的chafry
2022/10/30
7410
Dubbo2.7源码详解
Dubbo服务治理篇——改造低版本Dubbo,使其兼容Spring4或Spring5注解配置
特别说明:由于很多网友留言自身使用的Dubbo框架版本比较低,无法兼容Spring4或Spring5的注解配置,故本文只针对低版本Dubbo如何兼容Spring4或Spring5的注解配置给出相应的解决方案,目前,高版本Dubbo已经不存在与Spring4或Spring5的注解配置的兼容性问题。
冰河
2020/10/29
1.3K0
Dubbo源码-Dubbo是如何随心所欲自定义XML标签的
叨叨 今天考虑了很久要不要写这篇文章。 距离《Dubbo源码》系列的开篇到现在已经快两个月时间了。当时是想着工作上的RPC框架使用存在一些让人头疼的问题,就来看看Dubbo给出了一套什么样的解决方案。 结果,写完第一篇没几天,工作上因为要赶一个项目的进度,关小黑屋了,前段时间刚放出来-_-! 琢磨着,做事不能半途而废。今天就又打开了Dubbo项目,pull下代码,在十多个子模块之间来回滚动,感觉都不是好惹的,一时不知道从哪下手了。再一想,Dubbo源码系列不能就这么唐突的出一篇就结束了啊。 行,思来想去,还
JackieZheng
2018/05/28
8730
源码分析Dubbo服务提供者启动流程-上篇
本节将详细分析Dubbo服务提供者的启动流程,请带着如下几个疑问进行本节的阅读,因为这几个问题将是接下来几篇文章分析的重点内容。
丁威
2019/06/10
1.3K0
源码分析Dubbo服务提供者启动流程-上篇
Dubbo点滴(3)之服务配置Servi
spring加载xml或annotation,第一步需要将这些配置元数据载入spring容器中,首先确认下这些<dubbo:*>标签,对应的数据载体类。
py3study
2020/01/06
4430
dubbo源码学习(四)初始化过程细节:解析服务
今天将真正去看dubbo内部的实现过程,看dubbo的源码前我先把dubbo的用户指南和开发指指南大概的看了一遍,这样再看dubbo源码比较轻松。从用户指南和开发指指南可以找到相应的切入点,今天将介绍的是dubbo的初始化解析bean的过程:
BUG弄潮儿
2022/06/30
3440
源码分析Dubbo前置篇-寻找注册中心、服务提供者、服务消费者功能入口
上面通过dubbo提供的dubbo:application、dubbo:registry、dubbo:protocol、dubbo:provider、dubbo:service分别定义dubbo应用程序名、注册中心、协议、服务提供者参数默认值、服务提供者,这些配置后面的实现原理是什么呢?是如何启动并发挥相关作用的呢?
丁威
2019/06/10
1.2K0
源码分析Dubbo前置篇-寻找注册中心、服务提供者、服务消费者功能入口
【DUBBO】 Schema解析Spring扩展机制集成Spring
dubbo是如何做到与spring集成的?这都依赖于Spring提供的XML Schema可扩展机制,用户可以自定义XML Schema文件,并自定义XML Bean解析器,并集成到SpringIOC容器中。 创建自定义扩展,主要有以下步骤: 1、创建XML Schema 文件,描述自定义的合法构建模块,也就是xsd文件,主要用于定义数据约束; 2、自定义个处理器类,并实现NamespaceHandler接口,在里面注册各个标签对应的BeanDefinitionParser; 3、自定义一个或多个解析器,实现BeanDefinitionParser接口,用于定义Bean的解析逻辑;
spilledyear
2018/12/19
1.1K0
Dubbo源码学习一
首先,我们知道dubbo在以前都是基于zookeeper作为配置中心的,同时是建立在spring基础之上的。因此,就需要思考一些问题:
路行的亚洲
2020/07/16
4860
源码分析--dubbo服务端暴露
服务暴露的入口方法是 ServiceBean 的 onApplicationEvent。onApplicationEvent 是一个事件响应方法,该方法会在收到 Spring 上下文刷新事件后执行服务导出操作。方法代码如下:
luozhiyun
2019/08/28
3550
源码分析--dubbo服务端暴露
分布式服务Dubbo从入门到"精通"之Schema实现
前言 尽管使用了Dubbo许久,但其实对于其了解还是九牛一毛,上个月通读了Netty实战(粗略的了解),突然有了解读Dubbo源码的欲望,时不待我,那就赶紧开始吧。 熟悉Dubbo的朋友,可能都知道其采用全Spring配置方式,透明化接入应用,对应用没有任何API侵入,只需用Spring加载Dubbo的配置即可,Dubbo基于Spring的Schema扩展进行加载。 当然,如果你不想使用Spring配置,而希望通过API的方式进行调用,Dubbo也是支持的,但是官方是不推荐的(原因你猜)。 今天,就跟大家聊
小柒2012
2018/04/16
1.1K0
分布式服务Dubbo从入门到"精通"之Schema实现
Dubbo源码学习-服务发布
我们一般会把服务的信息放在spring的配置文件中,供dubbo解析调用。那么这些配置文件是怎么起作用的呢?
周同学
2020/03/20
9270
Dubbo源码学习-服务发布
dubbo(三)服务运行容器Container
Dubbo中的其中一个角色,服务运行容器Container。他是一个独立的容器,如果项目比较轻,没用到Web特性,因此不想用Tomcat等Web容器,则可以使用Main方法加载Spring容器。
虞大大
2020/09/24
1.4K0
Dubbo——服务发布原理
在使用Dubbo的时候你一定会好奇它是怎么实现RPC的,而要了解它的调用过程,必然需要先了解其服务发布/订阅的过程,本篇将详细讨论Dubbo的发布过程。
夜勿语
2020/09/07
6150
dubbo源码——服务提供者的服务暴露过程(二)
##1将address进行分割,和属性填充例如在一个标签中中配置了多个地址,example:<dubbo:registry
冰枫
2018/06/11
1.7K0
dubbo源码——服务提供者的服务暴露过程(二)
dubbo源码学习之服务发布调用链 消费者消费调用链(三)我太难了。。
dubbo 是基于 spring 配置来实现服务的发布的,那么一定是基于 spring的扩展来写了一套自己的标签,那么 spring 是如何解析这些配置呢?总的来说,就是可以通过 spring 的扩展机制来扩展自己的标签。大家在dubbo 配置文件中看到的dubbo:service ,就是属于自定义扩展标签
周杰伦本人
2022/10/25
4500
dubbo源码学习之服务发布调用链 消费者消费调用链(三)我太难了。。
dubbo源码学习(四):暴露服务的过程
dubbo采用的nio异步的通信,通信协议默认为 netty,当然也可以选择 mina,grizzy。在服务端(provider)在启动时主要是开启netty监听,在zookeeper上注册服务节点,处理消费者请求,返回处理后的消息给消费者,消费者使用服务时主要是订阅服务的节点,监听zookeeper节点目录,服务端的变化时zookeeper会推送给消费者,消费者重新缓存服务地址等。服务者、消费者、zookeeper三者之间都是长连接。
BUG弄潮儿
2022/06/30
3180
dubbo源码学习(四):暴露服务的过程
Dubbo源码之Spring整合
本文主要介绍了在不同的配置模式下,dubbo与spring整合的原理,即:xml配置、注解配置、自动化配置 三种模式下的配置生效原理。
spilledyear
2019/12/13
7950
相关推荐
dubbo基于spring运行原理解析
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验