dubbo+zookeeper 启动后为啥没有服务
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了dubbo+zookeeper 启动后为啥没有服务相关的知识,希望对你有一定的参考价值。
参考技术A 这个问题范围太大了吧!可以详细点么?dubbo是如何启动的
参考技术A已知,在项目启动过程中,我们会将dubbo的配置文件写到spring的配置文件里,如下xml文件:
<dubbo:application name="anyname_provider" />
<!-- 使用zookeeper注册中心暴露服务地址 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880" />
<!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="com.shxz130.provider.Provider"
ref="demoService" />
从官方文档中,我们能看到如下:
启动过程.png
也就是说spring启动过程中,随着Spring在初始化过程中,碰到dubbo命名的标签,如(<dubbo:service>,<dubbo:registry>)等标签,会由DubboNamespaceHandler类处理,具体原理见链接Spring自定义标签
DubboBeanDefinitionParser代码如下:
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());
遇到不同的标签,会由不同的Parser处理,这里重点看服务发布,这行代码:
registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
也就是说,当Spring容器处理完<dubbo:service>标签后,会在Spring容器中生成一个ServiceBean ,服务的发布也会在ServiceBean中完成。不妨看一下ServiceBean的定义:
public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener<ContextRefreshedEvent>, BeanNameAware
该Bean实现了很多接口,关于InitializingBean,DisposableBean,ApplicationContextAware,BeanNameAware,这些接口的使用介绍如下链接:
InitializingBean&DisposableBean
BeanNameAware& ApplicationContextAware
而在Spring初始化完成Bean的组装,会调用InitializingBean的afterPropertiesSet方法,在Spring容器加载完成,会接收到事件ContextRefreshedEvent,调用ApplicationListener的onApplicationEvent方法。
在afterPropertiesSet中,和onApplicationEvent中,会调用export(),在export()中,会暴露dubbo服务,具体区别在于是否配置了delay属性,是否延迟暴露,如果delay不为null,或者不为-1时,会在afterPropertiesSet中调用export()暴露dubbo服务,如果为null,或者为-1时,会在Spring容器初始化完成,接收到ContextRefreshedEvent事件,调用onApplicationEvent,暴露dubbo服务。
部分ServiceBean的代码如下:
public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener<ContextRefreshedEvent>, BeanNameAware //Spring容器初始化完成,调用public void onApplicationEvent(ContextRefreshedEvent event) if (isDelay() && !isExported() && !isUnexported()) if (logger.isInfoEnabled())
logger.info("The service ready on spring started. service: " + getInterface());
//暴露服务
export();
//判断是否延迟发布
private boolean isDelay()
Integer delay = getDelay();
ProviderConfig provider = getProvider(); if (delay == null && provider != null)
delay = provider.getDelay();
return supportedApplicationListener && (delay == null || delay == -1);
//当bean初始化完成调用
public void afterPropertiesSet() throws Exception //......此处省略10000行代码
if (!isDelay()) //暴露服务
export();
在export(),暴露服务过程中,如果发现有delay属性,则延迟delay时间,暴露服务,如果没有,则直接暴露服务。
public synchronized void export() //忽略若干行代码if (delay != null && delay > 0) //当delay不为null,且大于0时,延迟delay时间,暴露服务
delayExportExecutor.schedule(new Runnable() public void run() //暴露服务
doExport();
, delay, TimeUnit.MILLISECONDS);
else //直接暴露服务
doExport();
而在doExport()中,验证参数,按照不同的Protocol,比如(dubbo,injvm)暴露服务,在不同的zookeeper集群节点上注册自己的服务。
protected synchronized void doExport() //忽略10000行代码doExportUrls(); //忽略10000行代码
private void doExportUrls()
List<URL> registryURLs = loadRegistries(true); for (ProtocolConfig protocolConfig : protocols) //按照不同的Protocal暴露服务
doExportUrlsFor1Protocol(protocolConfig, registryURLs);
作者:一滴水的坚持
链接:https://www.jianshu.com/p/7f3871492c71
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
以上是关于dubbo+zookeeper 启动后为啥没有服务的主要内容,如果未能解决你的问题,请参考以下文章
为啥dubbo使用zkclient作为zookeeper的客户端
为啥dubbo使用ZkClient作为zookeeper的客户端
dubbo+zookeeper+dubbo管理控制台实践demo