服务暴露过程解析
当在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 { |
总结起来: