1. 服务导出的入口方法
2. 服务导出原理
2.1 刷新配置参数
2.1 确定协议,生成URL
2.3 启动对应协议的服务器
2.4 向注册中心注册服务
2.6 监听动态配置修改
通过在服务实现类上面加上@Service注解,Dubbo可以扫描并生成两个bean对象:Spring中的bean 和 ServiceBean,然后把服务导出到zookeeper、redis等注册中心!
上一篇文章中通过源码,我们明白了 ServiceBean的生成过程, 那么Dubbo是如何进行服务导出的呢?ServiceBean由于实现了ApplicationListener<ContextRefreshedEvent>,发布了一个容器刷新事件,意味着在spring容器启动完毕后,会调用onApplicationEvent方法,在方法内部调用export()向注册中心暴露服务!源码如下:
服务导出:主要是指 服务提供者向注册中心上提供服务的过程

Dubbo的服务导出主要做以下几件事情
根据配置方式的优先级,刷新Dubbo配置参数
确定协议,生成URL
根据服务的参数信息,启动对应的网络服务器(netty、tomcat、jetty等),用来接收网络请求
将服务的信息注册到注册中心
启动监听器,监听动态配置修改
一个Dubbo服务的配置参数有多种,比如version、group、delay、weight等等,这些配置参数的配置方式也有多种,而Dubbo选择配置方式的优先级从高到低如图所示,高优先级的配置覆盖低优先级的配置
Dubbo使用一个LinkedList集合来保存各种配置方式的配置信息,因为LinkedList是有序集合,方便后续对配置按优先级顺序进行覆盖和更新,源码如下所示:
有发现上面源码中缺失了@Service()中的配置了吗?Dubbo对@Service()上的配置优先级进行了特殊处理
我们可以自定义isConfigCenterFirst的属性,决定@Service()上的配置优先级
最后遍历LinkedList集合中的元素(配置方式),进行配置信息覆盖和更新
从以上分析我们可以看出,在服务导出之前,首先得确定服务的参数。服务的参数除开来自于服务的自身配置外,还可以来自比自身优先级高的配置。所以在确定服务参数时,需要先从上级获取参数,获取之后,如果服务本身配置了相同的参数,那么则进行覆盖
如果不同优先级之间没有出现冲突,则会互补。比如:@Service本身没有配置timeout参数,但是如果服务所属的应用的properties配置文件配置了timeout,那么这个应用下的服务都会继承这个timeout配置。
一个服务可以配置多个协议:
源码中会遍历所有的协议,每一种协议导出一个单独的服务
有了确定的协议,服务名,服务参数后,自然就可以组装成服务的URL了,在doExportUrlsFor1Protocol()方法中组装服务URL
有了准确的服务URL之后,就可以把URL注册到注册中心上去了,在注册之前,还需要获得注册中心的URL
注意:上面所说的服务URL或者注册中心URL,并不是浏览器上的url连接地址,而是一个名为URL的类,类内部封装了端口号、ip、协议等注册信息,如下所示
Dubbo在与其他组件交互的时候,会使用在服务URL中指定的协议,根据不同的协议启动不同的服务器,比如:
Http协议就启动Tomcat、Jetty。
Dubbo协议就启动Netty。
不能只启动Server,还需要绑定一个RequestHandler,用来处理请求。
比如,Http协议对应的就是InternalHandler。Dubbo协议对应的就是ExchangeHandler。
源码中方法如下:
有了服务URL 和 注册中心的地址的URL,就可以向zookeeper注册服务,注册失败的话会进行重试!
如上2.1中的配置,可以在zookeeper中生成两个服务
以dubbo协议的url为例,把dubbo协议的url通过编解码工具,解码后得到:
dubbo://192.168.100.1:20880/org.apache.dubbo.demo.DemoService?anyhost=true&application=dubbo-demo-provider1-application&bean.name=ServiceBean:org.apache.dubbo.demo.DemoService&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=org.apache.dubbo.demo.DemoService&logger=log4j&methods=sayHello&pid=12236&release=2.7.0&side=provider&timestamp=1614435347611&token=tulingtoken
可以看到注册到zookeeper上的服务其实就是这个服务配置的全部信息,其中token的主要作用是:调用服务时,为了分辨是否从zookeeper上拉取的服务!
服务在导出的过程中需要向动态配置中心的数据进行订阅,以便当管理人员修改了动态配置中心中对应服务的参数后,服务提供者能及时做出变化。
服Dubbo如果使用的是zookeeper作为配置中心,那么服务配置就存储在zookeeper节点上,就需要利用Zookeeper的Watcher机制,监听的是节点变化。所以在一个服务进行导出时,需要在服务提供者端给当前服务生成一个对应的监听器实例,这个监听器实例为OverrideListener,它负责监听对应服务的动态配置变化,并且根据动态配置中心的参数重写服务URL。
当动态配置中心修改了某个服务的配置后,就会触发OverrideListener中的notify对注册中心的URL进行重写覆盖,相当于重新发布服务,实现实时发布服务