美文网首页
dubbo之export浅析

dubbo之export浅析

作者: 我是你的小眼睛儿 | 来源:发表于2018-01-04 17:13 被阅读0次

    设计

    整体设计图(引用自官网)

    以ServiceConfig类为起点,主要过程为执行invoker和Exporter两个操作,这样看起来就清晰了。下面是整个export的时序图,从中可以看出ServiceConfig动作为createInvoker()和export(),Protocol执行了init()和exported()。

    时序图(引用自官网)

    注册中心暴露服务

    ServiceConfig 解析出的 URL 的格式为: registry://registry-host/com.alibaba.dubbo.registry.RegistryService?export=URL.encode("dubbo://service-host/com.foo.FooService?version=1.0.0")

    基于扩展点自适应机制,通过 URL 的 registry:// 协议头识别,就会调用 RegistryProtocolexport() 方法,将 export 参数中的提供者 URL,先注册到注册中心。

    再重新传给 Protocol 扩展点进行暴露: dubbo://service-host/com.foo.FooService?version=1.0.0,然后基于扩展点自适应机制,通过提供者 URL 的 dubbo:// 协议头识别,就会调用 DubboProtocolexport() 方法,打开服务端口。

    暴露服务主过程

    首先 ServiceConfig 类拿到对外提供服务的实际类 ref(如:HelloWorldImpl),然后通过 ProxyFactory 类的 getInvoker 方法使用 ref 生成一个 AbstractProxyInvoker 实例,到这一步就完成具体服务到 Invoker 的转化。接下来就是 Invoker 转换到 Exporter 的过程。

    Dubbo 处理服务暴露的关键就在 Invoker 转换到 Exporter 的过程,上图中的红色部分。 Dubbo 和 RMI 这两种典型协议的实现如下:

    • Dubbo 的实现
      Dubbo 协议的 Invoker 转为 Exporter 发生在 DubboProtocol 类的 export 方法,它主要是打开 socket 侦听服务,并接收客户端发来的各种请求,通讯细节由 Dubbo 自己实现。

    • RMI 的实现
      RMI 协议的 Invoker 转为 Exporter 发生在 RmiProtocol类的 export 方法,它通过 Spring 或 Dubbo 或 JDK 来实现 RMI 服务,通讯细节这一块由 JDK 底层来实现,这就省了不少工作量。

    暴露过程

    初始化的时候扫描配置文件,调用父类的方法registerBeanDefinitionParser(),存入一个名为parsers的hashMap中。

    image.png

    然后ServiceConfig类中的export方法不知道怎么的就执行了到这了,可以看到方法里可以立即加载和延时加载。

    image.png

    在调用当前类的doExport方法。方法中检查了加载的参数完不完整,正不正确。

    img

    接下来进入doExportUrls();方法,可以看到这里有个for循环,可以接受多个注册地址。

    image.png

    然后进入doExportUrlsFor1Protocol()方法,这个方法比较长,前半段负责检查拼装参数,还有一些逻辑,我觉得最重要的是下面箭头所指的两行代码,第一个是通过代理工厂生成代理方法,第二个是暴露服务。

    image.png

    第二个会进入ProtocolFilterWrapper的export方法,调用buildInvokerChain链

    image.png

    会默认进入DubboProtocol里,在这里的调用openServer()

    image.png

    仔细看看openServer()都干了啥,openServer调用createServer(url),createServer(url)中最重要的bind方法。

    image.png

    一步一步走下去,看到是调用了Transporters的bind方法。

    image.png

    点进去bind方法,可以看到getTransporter()这个方法返回了一个Transporter对象,看一下Transporter的接口,bind方法上有@Adaptive注解,在 Dubbo 的 ExtensionLoader 的扩展点类对应的 Adaptive 实现是在加载扩展点里动态生成。指定提取的 URL 的 Key 通过 @Adaptive 注解在接口方法上提供。对于 bind() 方法,Adaptive 实现先查找 server key,如果该 Key 没有值则找 transport key 值,来决定代理到哪个实际扩展点。默认使用SPI中设定的值,所以是netty。

    image.png
    transporter
    Adaptive

    在NettyServer继承了AbstractServer并且实现了Server接口,可以看到NettyServer在构造方法中实现了父类的构造方法,调用了doOpen,也可以看到打出start bind export的日志。

    image.png
    image.png
    image.png

    然后进入到RegistryProtocol的export方法,在这里注册服务到zookeeper


    image.png

    调用下面方法,设置协议等

    image.png

    执行这句 final Registry registry = getRegistry(originInvoker);


    image.png

    调用AbstractRegistryFactory的getRegistry

    image.png

    ZookeeperRegistryFactory的createRegistry的方法,因为ZookeeperRegistryFactory继承了AbstractRegistryFactory,AbstractRegistryFactory实现了RegistryFactory接口,而这个接口的getRegistry方法注解为@Adaptive({"protocol"}),之前有设置协议为zookeeper,所以根据名称选择了ZookeeperRegistryFactory的实现。

    image.png

    这里调用zookeeperTransporter的connect,就跟调用netty一样的


    image.png

    默认Zkclient的实现


    image.png
    在这里创建连接
    image.png

    创建成功之后,dubbo自己存一份


    image.png

    然后返回RegistryProtocol的export方法,添加一些订阅监听
    最后回到ServiceConfig的export方法,整个服务暴露完成。


    参考:http://dubbo.io/books/dubbo-dev-book/design.html
    各位大神多多指导

    相关文章

      网友评论

          本文标题:dubbo之export浅析

          本文链接:https://www.haomeiwen.com/subject/eptrnxtx.html