服务暴露过程解析
当在XML文件中配置下面内容,启动时Dubbo
即会发布demoService
服务,服务调用者皆可并在注册中心查到此服务提供者,并向其发起调用:
1 | <dubbo:application name="demo-provider"/> |
其中<dubbo:service>
用来初始化发布服务,其会被DubboBeanDefinitionParser
解析成ServiceBean
,并放在Spring容器中。afterPropertiesSet
方法初始化ServiceBean
。
其主要是从Spring容器
中获取Provider
、Application
、Module
、Registeries
、Monitor
、Protocol
对象设置到属性中。
- 没有配置
delay
属性时,直接调用export
暴露服务 - 配置了
delay
属性时,则会在Spring实例完所有bean后,发布ContextRefreshEvent
事件时,调用ServiceBean
(实现ApplicationListener
接口)的onApplicationEvent
方法进行export
1 | public void afterPropertiesSet() throws Exception { |
export
方法最关键的部分是执行doExportUrls
方法:
1 | private void doExportUrls() { |
接下来,就是Protocol
进行暴露以及发布服务:ServiceBean
中的Protocol
对应的是自适应类型Protocol
,调用export
方法时,其会根据参数Invoker的URL属性url.getProtocol()
来判定调用哪个Protocol
对象。上文中的registryURL.getProtocol
为registry
,所以回去调用RegistryProtocol
(会先调用包装类ProtocolListenerWrapper
、ProtocolFilterWrapper
)。
1 | public <T> Exporter<T> export(final Invoker<T> originInvoker) throws RpcException { |
上面的逻辑,可以分为两大部分:第一部分就是 本地服务暴露的逻辑,另一部分是注册服务的逻辑。因此,下面分别从这两部分说:
本地服务暴露:
doLocalExport
就是服务本地暴露的主体代码:
1 | private <T> ExporterChangeableWrapper<T> doLocalExport(final Invoker<T> originInvoker) { |
1 | openServer |
其中requestHandler
为DubboProtocol
的成员变量,当客户端发送请求时将由它进行处理:
1 | private ExchangeHandler requestHandler = new ExchangeHandlerAdapter() { |
Exchangers.bind(url, requestHandler)
监听端口,开启服务:
1 | Exchangers.bind(url, requestHandler) |
NettyServer
是监听端口,暴露服务的关键。其先设置bindAddress
、bindIp
、bindPort
属性,然后调用doOpen()
函数开启服务。
1 | public NettyServer(URL url, ChannelHandler handler) throws RemotingException { |
服务注册
1 | public <T> Exporter<T> export(final Invoker<T> originInvoker) throws RpcException { |
总结起来: