dubbo的服务发布

本篇了解一下dubbo的服务发布流程

一. 从配置文件走起

dubbo的服务发布
这个xml文件是dubbo提供的一个demo,用过dubbo的同学应该都了解这就是暴露一个接口demoService,那么这个接口如何暴露出去的呢?
既然是配置了这个xml就能暴露出去,那么肯定是从xml文件的配置开始,上图圈出来的红框中,很明显看出来是用的schema定义的xml文件,不了解的同学可以百度一下:schema自定义配置这个关键词,了解下schema自定义配置相关知识,这里就不再讲了,提供一个参考链接:https://www.cnblogs.com/jifeng/archive/2011/09/14/2176599.html
那么了解了schema自定义配置之后,就可以找到关于

<dubbo:service interface="org.apache.dubbo.demo.DemoService" ref="demoService"/>

这行代码具体怎么开始了
dubbo的服务发布
dubbo的服务发布
上面这两个图表示了service标签的定义
dubbo的服务发布
org.apache.dubbo.config.spring.schema.DubboNamespaceHandler#init中可以看到对service标签的解析器:new DubboBeanDefinitionParser(ServiceBean.class, true),所以我们进入org.apache.dubbo.config.spring.ServiceBean里面查看源码

二. ServiceBean

查看ServiceBean源码
dubbo的服务发布
上面这些实现的接口都是spring的接口,其实主要作用就是保存了spring容器的引用,并且监听了spring容器的启动事件,再看看ServiceBean的关系图
dubbo的服务发布
ServiceBean中有一个方法
dubbo的服务发布
他会发出一个Export事件
dubbo的服务发布
dubbo的服务发布
从注释可以发现是调用了org.apache.dubbo.config.spring.ServiceBean#exported,这个方法在上面截图有了,里面调用了父类的org.apache.dubbo.config.ServiceConfig#exporteddubbo的服务发布
可以看到依旧是发布了一个事件,这个事件点进去看:
dubbo的服务发布
实际是走到了org.apache.dubbo.config.ServiceConfig#export
dubbo的服务发布
上面这里和dubbo老版本的区别很大,都走了事件发布和监听,比较绕,我也没理解太懂,不用管太多,只要找到org.apache.dubbo.config.ServiceConfig#export这里,其实是真正开始发布服务,我们重点关注里面的方法:org.apache.dubbo.config.ServiceConfig#doExport
dubbo的服务发布
doExportUrls方法中,首先是加载配置文件中dubbo.registry.address的注册中心信息并组装到registryURLs,然后下面是一个for循环,这个循环的protocols是代表通信协议,for循环表示一个服务可以有多个通信协议,比如tcp、http,默认是dubbo的tcp协议
然后进入:org.apache.dubbo.config.ServiceConfig#doExportUrlsFor1Protocol这个方法,这个代码很多,前面都是各种校验和组装信息
dubbo的服务发布
重点在这里,可以看到注释写的是暴露本地服务和暴露远程服务,本地服务指的就是本地服务JVM里面的服务,不用通过zookeeper进行远程网络通信调用;那么远程服务就是通过zookeeper网络通信调用,暴露给可以给其他服务调用,这个应该不难理解
那么我们来看暴露本地服务的流程:
dubbo的服务发布
首先PROTOCOLPROXY_FACTORY分别都是从SPI中获取的,getAdaptiveExtension说明是获取的是个自适应的扩展类,那么分别看org.apache.dubbo.rpc.Protocolorg.apache.dubbo.rpc.ProxyFactory,这两个接口的@Adaptive注解都是标注在接口上,说明是动态生成的扩展类(这块是SPI的知识,不了解的可以看我之前的文章:dubbo的SPI)
dubbo的服务发布
其中ProxyFactory的作用就是为了获取一个接口的代理类,例如获取一个远程接口的代理。
ProxyFactory有2个方法,

  1. getInvoker:针对server端,将服务对象,如DemoServiceImpl包装成一个Invoker对象。
  2. getProxy :针对client端,创建接口的代理对象,例如DemoService的接口。

然后Protocol的默认实现是@SPI("dubbo")-> org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol
ProxyFactory的默认实现是@SPI("javassist")->org.apache.dubbo.rpc.proxy.javassist.JavassistProxyFactory
回到org.apache.dubbo.config.ServiceConfig#exportLocal方法中,看方法调用PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass, local),其实调用的就是org.apache.dubbo.rpc.proxy.javassist.JavassistProxyFactory#getInvoker
dubbo的服务发布
进入这个方法,首先看到是获取一个Wrapper,这个wrapper是从org.apache.dubbo.common.bytecode.Wrapper#makeWrapper里面获取来的,那么这个Wrapper的作用其实是类似springBeanWrapper的,spring 的BeanWrapper作用是:
BeanWrapper是对Bean的包装,其接口中所定义的功能很简单包括设置获取被包装的对象,获取被包装bean的属性描述器,由于BeanWrapper接口是PropertyAccessor的子接口,因此其也可以设置以及访问被包装对象的属性值。BeanWrapper大部分情况下是在spring ioc内部进行使用,通过BeanWrapper,spring ioc容器可以用统一的方式来访问bean的属性
那么dubbo的Wrapper其实和他差不多,在dubbo里面它的作用也是:包装一个接口或者类,可以通过Wrapper对接口或者类的实例进行取值、赋值、或者制定方法的调用
回到代码中,拿到这个Wrapper包装类之后,new AbstractProxyInvoker<T>(proxy, type, url)创建了一个Invoker这个Invoker它是一个可执行的对象,能够根据方法的名称、参数得到相应的执行结果,它里面有一个很重要的方法:org.apache.dubbo.rpc.Invoker#invoke(Invocation invocation),这个方法的入参Invocation代表了要执行的方法和参数等重要信息,Invoker在dubbo里面相当的重要,这里先说一下概念:
Invoker有3种类型的Invoker

  1. 本地执行类的Invoker
    server端:要执行 demoService.sayHello,就通过InjvmExporter来进行反射执行demoService.sayHello就可以了。

  2. 远程通信类的Invoker
    client端:要执行 demoService.sayHello,它封装了DubboInvoker进行远程通信,发送要执行的接口给server端。
    server端:采用了AbstractProxyInvoker执行了DemoServiceImpl.sayHello,然后将执行结果返回发送给client.

  3. 多个远程通信执行类的Invoker聚合成集群版的Invoker
    client端:要执行 demoService.sayHello,就要通过AbstractClusterInvoker来进行负载均衡,DubboInvoker进行远程通信,发送要执行的接口给server端。
    server端:采用了AbstractProxyInvoker执行了DemoServiceImpl.sayHello,然后将执行结果返回发送给client.

上一篇:Jmeter测试Webservice和http invoke


下一篇:Dubbo的服务暴露过程