dubbox 主流程源码分析

customer

  • customer 生成invoke proxy:

  a.spring容器启动时通过方法读取xml配置文件(dubbo-demo-consumer.xml)。


  b. 读取配置文件spring.handlers,获取nameplace为http://code.alibabatech.com/schema/dubbo的标签处理类DubboNamespaceHandler。标签类注册了各标签对应的标签解析器 ,如dubbo:application对应DubboBeanDefinitionParser(ApplicationConfig)。

  c.spring容器通过DubboBeanDefinitionParser类的对象来解析xml文件中的标签,生成ReferenceConfig等配置对象;比如dubbo:reference对应生成ReferenceBean。

  d.spring完成这些bean的初始化,ReferenceBean实现了接口InitializingBean,其afterPropertiesSet方法被调用:首先,如果customer、appliction、module、registry、monitor等配置没被初始化,则初始化这些配置bean;<这步其实是Reference确认生成Invoker所需要的组件是否已经准备好,都准备好后我们进入生成Invoker的部分,getObject会调用父类ReferenceConfig的init方法完成组装 ReferenceConfig.init() 至此Reference在关联了所有application、module、consumer、registry、monitor、service、protocol后调用对应Protocol类的refer方法生成InvokerProxy。 当用户调用service时dubbo会通过InvokerProxy调用Invoker的invoke的方法向服务端发起请求。客户端就这样完成了自己的初始化>


  e.ReferenceBean实现了FactoryBean,Spring调用getObjectFromFactoryBean获取beanObject时调用getObject方法,getObject会调用父类ReferenceConfig的init方法完成组装 ReferenceConfig.init();

1),装载了application、module、consumer、reference的所有属性信息;
Wrapper com.alibaba.dubbo.common.bytecode.Wrapper.getWrapper(Class c)->
com.alibaba.dubbo.common.bytecode.Wrapper.makeWrapper()将远程调用接口class生成代理wrapper类(还不知道用处);
2),创建远程调用代理ReferenceConfig.createProxy
//此处举例说明如果是Dubbo协议则调用DubboProtocol的refer方法生成invoker,当用户调用service接口实际调用的是invoker的invoke方法
invoker = refprotocol.refer(interfaceClass, urls.get(0));
ProtocolFilterWrapper.refer->RegistryProtocol.refer该方法分以下两步:

->ZookeeperRegistryFactory.getRegistry获取注册中心,这里以zookeeper为注册中心。期间会初始化zookeeper连接
->RegistryProtocol.doRefer

1、产生consumer地址并向注册中心注册该consumer

2、并订阅porviders、该过程会向注册中心获取provider的 地址列表并写回invoker中;在refreshInvoker过程中调用方法->toInvokers->ProtocolListenerWrapper.refer构造invoker过程中使用 构造服务调用 filter,比如监控,日志等;使用配置的SerializationOptimizerImpl实现类序列化用:首先,ProtocolFilterWrapper.refer->DubboProtocol.refer->DubboProtocol.initClient(URL url)创建和provider的连接
,该方法选择底层协议,连接属性等(netty);使用获得的Client创建doubboInvoke。其次,将该doubboInvoke传入buildInvokerChain方法构建invoke chain;然后包装Invoker返回。

3、 cluster.join(directory) ->MockClusterWrapper.join->FailoverCluster.join生成FailoverClusterInvoker对象,返回MockClusterInvoker对象;


  f.在ReferenceConfig.createProxy方法中最后一步,使用MockClusterInvoker创建 proxyFactory.getProxy(invoker);
-》StubProxyFactoryWrapper.getProxy->AbstractProxyFactory.getProxy(EchoService)->JavassistProxyFactory.getProxy->Proxy.getProxy.newInstance(new InvokerInvocationHandler(invoker));
Proxy.getProxy通过字节码生成实现了用户定义远程接口和EchoService接口的类字节码,并Classloader到内存中,生成实现代码中使用InvocationHandler代理远程调用。如上示例中使用 InvokerInvocationHandler做为所有远程调用入口。参见生成Proxy的代理对象实例。

 

 

 

  • proxy的使用,来进行远程调用:

    MockClusterInvoker.invoke 做rpc远程调用

    FailoverClusterInvoker.select, 通过loadbalance在invoker ls中选取invoker,其中LoadBalance.select实现负载算法。
    DubboInvoker。doInvoke
    NettyClient(AbstractClient).send(Object o)
    com.alibaba.dubbo.remoting.transport.netty.NettyCodecAdapter.encode/decode() 实现对象的序列化反序列化

    CodecSupport.getSerialization获取序列化类型kryo
    NettyClient 中初始化了netty的使用,包含decode encode的配置channal的初始化。
    ExchangeCodec.encodeRequest,对象的序列化反序列化并发送
    DubboCodec.encodeRequestData中配置远程调用的协议,接口,方法,参数等方法。

其它:

com.alibaba.dubbo.common.extension。ExtensionLoader。createAdaptiveExtensionClassCode()生成扩展接口的java代码
com.alibaba.dubbo.registry.support.FailbackRegistry.register 向服务器端发送注册customer.
com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper.buildInvokerChain() 构造服务调用filter链,比如监控,日志等
FailbackRegistry.subscribe // 向服务器端发送订阅请求
FailoverClusterInvoker.doInvoke //失败转移,当出现失败,重试其它服务器,通常用于读操作,但重试会带来更长延迟。

spi机制..待补充。

provider

使用Annotation和xml配置服务:AnnotationBean.postProcessAfterInitialization

Wrapper将需要包装的对象包装,然后通过其invokeMethod方法调用原对象的方法;
1.spring通过DefaultListableBeanFactory.registerBeanDefinition将Annotation、xml和自定义的bean(如直接调这个方法将ApplicationConfig)注册进去;其中AnnotationBean将标签dubbo:annotation所定义的类扫描package下面的生命为服务的类注册到bean中(AnnotationBean.postProcessBeanFactory中先注册Service Annotation表示该annotation需要生成bean,调用ClassPathBeanDefinitionScanner.san方法扫描)。


2.AnnotationBean实现了接口BeanPostProcessor,所有bean实例化后处理方法postProcessAfterInitialization被调用,声明为 @Service 的Service bean被处理:

a、普通的javabean(声明为@Service的bean,实际提供服务)被包装为ServcieBean并通过其afterPropertiesSet()方法初始化其applicion,module,registry等信息;
b、调用serviceConfig.export()方法发布服务bean

b1、ServiceConfig.export->doexport->ServiceConfig.doExportUrls,先获取注册中心地址,再对注册的每一个Protocol(rest、dubbo等)发布doExportUrlsFor1Protocol
b2、对rest协议的发布过程为列分析,先在方法doExportUrlsFor1Protocol中准备发布的ip和端口,需暴露的服务名和服务方法,以及服务的运行容器(tomcat),准备好好交给exportLocal暴露本地服务和暴露远程服务;
b3、暴露本地服务:
protocol.export(proxyFactory.getInvoker(ref, (Class) interfaceClass, local))
proxyFactory.getInvoker->StubProxyFactoryWrapper.getInvoker->JavassistProxyFactory.getInvoker(这里返回的Invoker为ref的两层包装,Wrapper,AbstractProxyInvoker)
protocol.export->ProtocolListenerWrapper.export->ProtocolFilterWrapper.export:buildInvokerChain构造出声明为<@Activate(group = Constants.PROVIDER)>的filter 链;->protocol.export->InjvmProtocol.export返回InjvmExporter对象,最后被包装为ListenerExporterWrapper。
b4、暴露远程服务:
获取注册中心url();
proxyFactory.getInvoker->StubProxyFactoryWrapper.getInvoker->JavassistProxyFactory.getInvoker(这里返回的Invoker为ref的两层包装,Wrapper,AbstractProxyInvoker)
protocol.export(invoker)->ProtocolListenerWrapper.export->ProtocolFilterWrapper.export->RegistryProtocol.export

--》RegistryProtocol.doLocalExport->ProtocolListenerWrapper.export->ProtocolFilterWrapper.export->RestProtocol(AbstractProxyProtocol).export->RestProtocol.doExport 在该方法中,首先从url中获取服务器类型(tomcat),然后 RestServerFactory.createServer创建server,在BaseRestServer.start中启动server:doStart< httpBinder.bind>->TomcatHttpBinder.bind 启动tomcat服务器。其次,server.deploy将资源部署到server中。至此,该rest服务具备向外提供服务的能力。
RegistryProtocol.export

--》getRegistry获取注册中心,然后向注册中心注册服务提供provider的url
b5、对dubbo协议发布过程分析,doExportUrlsFor1Protocol步骤同上,RestProtocol.export替换为DubboProtocol.export, ->DubboProtocol.openServer->DubboProtocol.createServer->Exchangers.bind->HeaderExchanger.bind->Transporters.bind->NettyTransporter.bind启动netty server服务

转载于:https://www.cnblogs.com/edjoin/p/6235408.html

你可能感兴趣的:(dubbox 主流程源码分析)