这篇文章来叙述对dubbo的服务暴露前的准备工作:

使用Spring配置文件,通过main方法来启动spring容器,来观察dubbo服务的启动过程。

dubbo配置文件

    <context:component-scan base-package="com.wk.order.service.impl,com.wk.order.facade.impl"/><dubbo:application name="dubbo-order-service"/><!--<dubbo:registry address="multicast://224.5.6.7:1234" />--><dubbo:registry protocol="zookeeper" address="127.0.0.1:2181" /><dubbo:protocol name="dubbo" port="20880"/><dubbo:service interface="com.wk.common.facade.OrderFacade" ref="orderFacadeImpl" loadbalance="roundrobin"/>

在说明暴露服务的流程之前,先明确知道几个对象,在dubbo里,默认使用JavassisFactory动态代理工厂来动态的产生扩展对象,然后根据扩展对象的export方法,根据url的参数配置,例如上述为dubbo协议,注册中心为zookeeper。这样呢就会根据url的配置使用DubboProtocol来进行服务的暴露,创建NettyServer。默认为netty启动。默认也是Dubbo。会使用ZookeeperRegistry把服务注册的注册中心。

在Spring容器启动时,会对Bean进行加载,Dubbo通过Spring自定义标签扩展了自己的标签。把属于Dubbo的实体Bean注册到Spring里。

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 DubboBeanDefinitionParser(AnnotationBean.class, true));}

上面注册了ServiceBean这个类,那么ServiceBean是什么什么东西呢,观察ServiceBean对象,它实现了InitializingBean接口,在该接口中有一个afterPropertiesSet方法,在Bean的属性初始化时,Spring会默认调用该方法。该方法里调用了关于dubbo的开始 export方法。那么dubbo的服务暴露export方法就在这里开始起航了。

第一步:在afterPropertiesSet里会从applicationContext里获取诸多实例,诸多实例就是上述注册器里的Bean.class。经过这一层之后,就会调用export方法。此时在ServiceConfig对象里,已经有了关于dubbo配置的一些内容。

走入export方法后共有多个方法一连串的调用:

doExport方法对一些配置进行检测和获取,检查provider,application,module,registries,monitor这些参数是否为空,是否是GenericService类型的服务,检查要注册的bean的引用和方法等。虽然不知道这些是做什么用的。

doExportUrls:很明显,它这是获取注册中心的url路径。因为dubbo支持多注册中心,所以需要获取多个注册中心的url。

registry://127.0.0.1:2181/com.alibaba.dubbo.registry.RegistryService?application=dubbo-order-service&dubbo=2.5.7&pid=9720&registry=zookeeper&timestamp=1535884939183

doExportUrlsFor1Protocol:该方法是真正的开始暴露服务了,在这个方法里有一大堆的参数在往map里塞。这就是在为服务暴露做准备。dubbo的主线是Invoker对象,而url就是包含各种配置在内的一个协议字符串。根据这个字符串能够做好多的事情。

doExportUrlsFor1Protocol方法很长,其中有几处需要关注:

1、获取主机地址,这段逻辑曾经在线上部署时,出现过问题。如今恍然大悟。在获取主机地址的逻辑中:优先从配置里获取主机地址,否则从本地的InetAddress获取地址,再者从Socket里获取地址。

2、本地服务不需要notify。即injvm是不需要进行notiry的。injvm是本地暴露的协议。类似:registry等协议。

   if ("injvm".equals(protocolConfig.getName())) {protocolConfig.setRegister(false);map.put("notify", "false");}// 导出服务String contextPath = protocolConfig.getContextpath();if ((contextPath == null || contextPath.length() == 0) && provider != null) {contextPath = provider.getContextpath();}String host = this.findConfigedHosts(protocolConfig, registryURLs, map);Integer port = this.findConfigedPorts(protocolConfig, name, map);

在一大堆参数配置完毕后,根据scope的配置决定是否要进行本地暴露。

本地暴露过程:本地暴露过程相对简单,主要是通过扩展机制使用JavassitFactory对业务类进行动态代理生成一个动态代理对象,使用injvmProtocol把invoker包装为一个Exporter。最后放到ServiceConfig的一个属性exports里。exports是一个list集合。

对于本地暴露的过程,为什么要这样进行暴露,以及包装过程中都做了什么,有什么值得去包装的呢?

根据我的理解,在这里其实是一个IOC和AOP的体现,从Dubbo的扩展机制,实现了一个SPI自定义扩展,你可以加上无数个扩展。再加上Adaptive增强注解+装饰机制达到了AOP的效果。对于这里的包装有什么效果呢,目前知道和过滤器链有关。先打上个标记。

对于远程暴露,和本地暴露也是同样的过程,只不过Dubbo在把Invoker包装为Exporter的过程中,做了两件事情:

1、创建序列化和反序列化实例,根据扩展机制生成Server实例,默认使用NettyServer,还给Server添加了经过一系列包装的handler对象,因为对网络编程编码,解码,Netty拆包,粘包,dubbo的线程池处理不了解,只能先到这里了。总之创建Server实例完成之后,就返回了Exporter对象。

2、在返回Exporter对象之后,RegisterProtocol继续发挥它的余热,但是却也做了一个了不起的事情。接下来它需要把服务通过扩展机制得到的注册中中心,把服务注册到注册中心上。

在返回Export对象之后,register第一个要做的事情就是打通注册中心,本例为zookeeper,在看源码过程中,这里会在zk上先建立一个/dubbo的节点,并生成一个监听。然后返回回来后,依据提供者的配置,获取url参数。接下来的事情就比较简单了,根据zkClient直接在dubbo上创建节点就OK了。

还会调用registry的subscribe方法,这里主要是加了注册订阅Listener,在创建出其他节点之后会调用notify方法。notify方法会做两件事,1. 会将url改动更新到缓存的配置文件中。2. 会通知listener变动,此通知为全量通知

下面来看一下我的zookeeper的节点内容,从第一行看起,会看到在 /dubbo/com.wk.common.facade.OrderFacade下一共有4个节点,分别是 consumers,configurators,routers,providers。其中在providers下的内容见第一个红框,根据显示,可以看到providers下有一大堆的内容,想来这就是我们在dubbo上注册的那个url喽。

对于configurators和routers都是为空,相比应该是在dubbo控制台上做一些处理,之后就会有内容了。也就是说,当这些节点有变化的时候,就会通知ZookeeperRegister发生变化。

从官方的说明来说,服务启动的时候,会向providers目录下写入自己的url地址。估计我这里的consumbers是以前消费者启动写入的。

暂时先这样,有不同见解的,欢迎评论。

Dubbo——服务暴露过程分析相关推荐

  1. 面试官问我:解释一下Dubbo服务暴露

    今天我们要分析的就是Dubbo的服务暴露过程,这个过程属于Dubbo的核心过程之一了,因为Dubbo的大体流程就是服务暴露->服务引用->服务消费这几个主流程,当然还会涉及到注册发现.负载 ...

  2. Dubbo服务暴露的流程

    在Dubbo服务暴露中,需要被暴露的服务的接口类首先会通过proxyFactory代理工厂获得代理的对象invoker,而暴露之后的服务被调用,也将都会通过这个invoker来调用相关的类. 在dub ...

  3. Dubbo服务暴露原理

    服务暴露原理 配置文件 IOC容器启动,加载配置文件的时候 Dubbo标签处理器,解析每一个标签 封装成对应的组件 service 解析service标签 将service标签信息,封装成Servic ...

  4. Dubbo服务暴露(导出)流程

    Dubbo作为一个Rpc框架,服务端必须得将自己暴露出去,以便客户端的调用,所以我们来看一下dubbo是如何将服务进行暴露的. 首先我们知道,启动dubbo得进行一些配置,如下图所示的一些dubbo标 ...

  5. dubbo服务暴露流程总结

    这篇文章主要总结一下dubbo服务端启动的时候服务暴露过程,虽然官方网站和各种博客上已经有很多介绍服务暴露的帖子,但还是想把自己跟源码过程中遇到的问题和心得记录下来,算是个总结,并且本篇文章是基于du ...

  6. dubbo服务暴露原理解析

    配置解析 dubbo 的各个配置项,详细的可以参考官网 只有 group,interface,version 是服务的匹配条件,三者决定是不是同一个服务,其它配置项均为调优和治理参数 所有的配置最终都 ...

  7. 阿里面试官:你知道Dubbo的服务暴露机制么?

    点赞再看,养成习惯,微信搜一搜[三太子敖丙]关注这个喜欢写情怀的程序员. 本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试完整考点.资料以及我的系 ...

  8. Dubbo/Dubbox的服务暴露(一)

    前言 源码入手 平时我要了解一个框架,基本会去从他的Listener入手,如果web.xml中没有配置listener可能还会有 filter,这是spring给我们的启示,可是当要去了解dubbo的 ...

  9. php dubbo 接口测试工具,dubbo服务自动化测试搭建

    java实现dubbo的消费者服务编写:ruby实现消费者服务的接口测试:通过消费者间接测试dubbo服务接口的逻辑 内容包括:dubbo服务本地调用环境搭建,dubbo服务启动,消费者部署,脚本编写 ...

最新文章

  1. 跑python gpu利用率低_训练效率低?GPU利用率上不去?快来看看别人家的tricks吧~...
  2. Spring State Machine:它是什么,您需要它吗?
  3. Centos7使用Docker创建Oracle11g
  4. 分享一个在线vim网站
  5. C++基础知识总结----类的进阶知识点
  6. 【图神经网络入门】GAT图注意力网络
  7. 严加监管是否能解决超载问题
  8. Gradle教程--基础篇
  9. red5搭建流媒体直播系统
  10. 生物信息学基础知识Day4
  11. 清空回收站如何找回?
  12. NRZ、RZ信号的时频域区别及它们的谱效率
  13. 智能手表,不再只是手机品牌的“附属品”
  14. c语言课程设计雪花飞舞,雪花飞舞--c语言课程设计.doc
  15. ai人工智能课程百度云_云AI就像核电
  16. matlab弹道仿真,战役战术导弹弹道仿真在simulink下如何实现
  17. 两图像间的单应性矩阵估计
  18. 大众mpv_大众mpv商务车7座车型 大众mpv都有哪些?
  19. 宽带语谱图(wideband spectrogram)和窄带语谱图(narrowband spectrogram)的区别
  20. 实战4 - 汽车行驶工况构建

热门文章

  1. 苹果自带的清理软件_软件| 卸载软件、清理文件,你只需Revo Uninstaller Pro(自带注册程序)...
  2. Arduino基础与常用函数
  3. Java中的异常分类[乐乐独记]
  4. 爬虫:Iron WebScraper 2022 for NET
  5. 等比缩放公式_等比缩放算法
  6. python设置默认utf8编码_Python设置默认编码为utf8的方法
  7. [编译原理课设] 自动机的状态转换图表示
  8. 华硕服务器不分区重装系统,华硕笔记本重装系统不能进入系统怎么办
  9. oracle 实用记录
  10. DHTMLX JS Gantt Library 7.1.13