服务暴露:
1:serviceBean 继承 ApplicationListener 监听了spring的启动完成事件
2:判断延迟加载或者立刻加载
3:检查配置文件 (monitor,application,protocol,registry等)
4:构建URL参数,如端口,IP,协议,暴露的方法,接口等
5:判断是否是注册中心的暴露方式 或者直接引用暴露等
6:通过ProxyFactory的自适应扩展类获取invoker,用于服务调用
6.1:默认是javassitProxyFactory,会通过Wrapper封装代理类,用于rpc请求的时候,找到具体的服务方法执行,wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments)
6.2:返回一个匿名内部类AbstractProxyInvoker,执行的就是wrapper的invokeMethod方法
7:包装成为DelegateProviderMetaDataInvoker,方便携带暴露的invoker和各自config数据
8:通过Protocol的自适应扩展类,把Invoker暴露出去,生成exporter
8.1:使用注册中心的话,默认使用的是RegistryProtocol类进行暴露
8.1.1:例如Dubbo协议,通过DubboProtocol将invoker转换为DubboExporter
8.1.1.1 通过使用ProtocolFilterWrapper包装类,将Invoker封装成为provider端的责任链Invoker
8.1.1.2 将DubboExporter存储在本地缓存dubboProtocol.exporterMap,
exporterMap主要用于RPC远程调用的时候,通过远程方法的入参,找到具体的exproter,然后获取到具体Invoker,进行服务调用
8.1.1.3 创建服务端
8.1.1.4:通过Exchanger扩展,获取到默认的HeaderExchanger类
new HeaderExchangeServer(Transporters.bind(url, new ChannelHandler[]{new DecodeHandler(new HeaderExchangeHandler(handler))}));
1-> new HeaderExchangeHandler(handler) 将DubboProtocol生成的requestHandler保存在HeaderExchangeHandler的handler属性中
2-> new DecodeHandler() 将HeaderExchangeHandler实例保存在DecodeHandler实例的handler属性中。
3-> new ChannelHandler[] 创建ChannelHandler数据,保存DecodeHandler实例
4-> Transporters.bind() 默认生成的是NettyServer。
5-> new HeaderExchangeServer(),将创建的NettyServer客户端存放在HeaderExchangeServer实例的server节点中
HeaderExchangeServer用于开启心跳相关逻辑
8.1.2 将创建的服务端HeaderExchangeServer保存在DubboProtocol.serverMap内存中。
8.2:在注册中心上注册具体暴露的URL信息,并且订阅override
8.3:返回Exporter
概括:
服务暴露通过监听spring服务启动事件,然后进行服务暴露
1:通过ProxyFactory扩展,将暴露的服务类封装成为Invoker,用于RPC请求处理的服务调用
2:通过Protocol扩展,如果有注册中心,则把URL注册到注册中心,然后将Invoker封装成为Exporter,并且启动服务,默认使用的是Netty
3:启动netty服务,使用Transport扩展创建Netty服务端,然后通过Exchanger扩展,封装Netty服务端,提供request和response能力
服务引用(默认是Zookeeper注册中心和Dubbo协议)
第一阶段,代理服务生成
1:referenceBean 继承了 spring的FactoryBean(工程bean,通过getObject来获取生成实例)
2:构建comsumer端的URL
3:创建代理,通过Protocol自适应扩展,获取RegistryProtocol扩展类
4:构建RegistryDirectory服务目录,保存注册中心订阅到的providers节点的信息(URL信息)生成的Invokers,并且注入到FailoverclusterInvoker实例中
4.1:注册中心的监听,RegistryDirectory实现了NotifyListener接口,会通过该接口进行监听回调,将监听到的invoker保存在registryDeirecory实例的urlInvokerMap内存中。
4.2:注册中心监听获取到的节点信息,通过Protocol拓展类(根据URL的协议,例如DubboProtocol),获取具体的Invoker,
创建DubboInvoker实例,其中包含client客户端属性(默认是nettyClient),(后续RPC调用的时候需要用到)
4.2.1:通过Exchanger自适应扩展,默认获取的是HeaderExchanger
4.3.1.1:把dubboProtocol的requestHandler注入到HeaderExchangeHandler的handler属性中
4.3.1.2:同上,将HeaderExchangeHandler包装成DecodeHandler,然后存储在ChannelHandler数组中
4.3.1.3:将handler数组通过Transporters扩展,创建nettyClient(此处使用dubbo默认策略)
4.3.1.4:将生成的nettyClient存放在HeaderExchangeClient类中,主要是做了心跳相关操作
4.3:将生成的client通过ReferenceCountExchangeClient包装,提供引用计数功能
4.4:其中会通过ProtocolFilterWrapper把DubboInvoker实例包装成责任链。
5:通过Cluster扩展实例化FailoverClusterInvoker,并把registryDirectory保存在FailoverClusterInvoker中。
Invoker invoker = cluster.join(directory);
6:把failoverClusterInvoker实例通过ProxyFactory自适应扩展类,生成代理对象,默认使用的是JavassistProxyFactory
6.1:使用java jdk动态代理的方式以及字节码动态生成Proxy实现类和接口代理类proxy$n ,内部逻辑通过Proxy子类newInstance一个proxy$n的代理类
6.2:接口代理类proxy$n,内部使用jdk动态代理的方式调用具体的接口方法,InvocationHandler.invoke()
6.3:InvocationHandler的实现类是InvocationHandler,内部最终调用的就是Invoker.invoker(new RpcInvocation),该invoker是failoverClusterInvoker
7:返回ProxyFactory.getObject生成的代理类,也就是接口代理类proxy$n
第二阶段:RPC远程调用
1:proxy->client(例如nettyClient)->[header(Codec)->body(Serialization)]->server->Dispatcher->Threadpool->implement
2:client到Server是Transport阶段
3:调用proxy$n.xxxMethodName()方法,会执行到InvokerInvocationHandler.invoke方法,内部调用failoverClusterInvoker.invoke()方法。
4:会执行到failoverClusterInvoker的父类AbstractClusterInvoker,
4.1:获取到服务目录(RegistryDirectory),内部经过了router路由规则过滤
4.2:获取LoadBalance扩展类到负载均衡类,默认是RandomLoadBalrance
4.3:执行模板方法:doInvoke(),由failoverClusterInvoker实现
5:FailoverClusterInvoker通过获取到的服务目录,然后经过负载均衡,选择出一个invoker(这是经过责任链包装后的Invoker,最终会调用到DubboInvoker.doInvoke()),执行其invoke方法
6:是否是单向请求,是否是异步请求,还是同步请求,在此实现,例如同步的话,get()方法有框架调用进行阻塞。
7:将请求用HeaderExchangeChannel封装Request,然后交由内部的handler属性(这个地方是nettyClient) (HeaderExchangeChannel逻辑处理request和response逻辑,做数据交换处理) (HeaderExchangeClient 有什么用处呢?答案是封装了一些关于心跳检测的逻辑)
8:NettyCient发送最终的请求,其实就是netty操作 NettyChannel类的send() ChannelFuture future = this.channel.writeAndFlush(message);
领域模型
在 Dubbo 的核心领域模型中:
Protocol 是服务域,它是 Invoker 暴露和引用的主功能入口,它负责 Invoker 的生命周期管理。
Invoker 是实体域,它是 Dubbo 的核心模型,其它模型都向它靠扰,或转换成它,它代表一个可执行体,可向它发起 invoke 调用,它有可能是一个本地的实现,也可能是一个远程的实现,也可能一个集群实现。
Invocation 是会话域,它持有调用过程中的变量,比如方法名,参数等。
ProxyFactory 服务暴露方用于创建invoker。 服务引用方用于生成接口代理。
Protocol 服务暴露用于将invoker暴露成DubboExporter。服务引用用于生成Invoker。
Invoker 服务暴露方用于服务调用。服务引用方用于RPC调用。