总体分层
总体分为业务层(Biz),RPC层,Remote层
进一步划分可以分成10层,左边的是具体的分层,右边是该层中比较重要的接口
Dubbo核心组件
层次名 | 作用 |
---|---|
Service | 业务层 包括业务代码的接口与实现,即开发者实现的业务代码 |
config | 配置层 主要围绕ServiceConfig(暴露服务配置)和ReferenceConfig(引用服务配置)两个实现类展开,初始化配置信息 可以理解为该层管理了整个Dubbo配置 |
proxy | 服务代理层 在Dubbo中,无论生产者还是消费者,框架都会生成一个代理类,整个过程对上层是透明的.当调用一个远程交口时,看起来就像是调用了一个本地接口一样,代理层会自动做远程调用并返回结果,即让业务层对远程调用无感 |
cluster | 集群容错层 该层主要负责:远程调用失败时的容错策略(如失败重试,快速失败);选择具体调用节点时的负载均衡策略(如随机,一致性Hash等);特殊调用路径的路由策略(如某个消费者只会调用某个特定的生产者) |
monitor | 监控层 这一层主要负责监控统计调用次数和调用时间等 |
protocol | 远程调用层 封装RPC调用具体过程,Protocol是Invoker暴露和引用的主功能入口,它负责管理Invoker的整个生命周期.Invoker是Dubbo的核心模型,框架中所有其他模型都向它靠拢,或者转换成它.允许它发起invoke调用,它可能是执行一个本地的接口实现,也可能是一个远程的实现,还可能一个集群实现 |
exchange | 信息交换层 建立Request-Response模型,封装请求响应模式,如把同步请求转化为异步请求 |
transport | 网络传输层 把网络传输抽象为统一接口,如Mina和Netty虽然接口不一样,但是Dubbo在它们上面又封装了统一接口.用户也可以根据其扩展接口添加更多的网络传输方式 |
Serialize | 序列化层 负责管理整个框架网络传输时的序列化/反序列化工作 |
Dubbo总体调用过程
服务提供方
首先服务提供者在框架启动时,会初始化服务实例,通过Proxy组件调用具体协议(Protocol),把服务端要调用的接口封装成Invoker,然后转换成Exporter,这个时候框架会打开服务端口等并记录服务实例到内存中,最后通过Register把服务元数据注册到注册中心
Proxy
Dubbo只需要引用一个接口就可以调用远程的服务,并且只需要像调用本地方法一样调用即可.其实Dubbo框架为我们生成了代理类,调用的方法其实是Proxy组件生成的代理方法,会自动发起调用返回结果.
Protocol
协议是对数据格式的一种约定.它可以把我们对接口的配置根据不同的协议转换成不同的Invoker对象.如DubboProtocol可以把XML文件中一个远程接口的配置转换成一个DubboInvoker.
Exporter
用于暴露到注册中心的对象,它的内部属性持有了Invoker对象,可以认为它是在Invoker上包了一层
Register
把Exporter注册到注册中心
服务调用方
消费放会在启动时会通过Registry在注册中心订阅服务端的元数据(包括IP和端口),这样就可以得到服务提供方暴露的服务了.
首先,调用过程也是从一个Proxy开始的,Proxy持有了一个Invoker对象,然后触发invoker调用.在invoker调用过程中,需要使用Cluster负责集群容错.Cluster在调用之前会通过Director获取所有可以调用的远程服务Invoker列表.由于可以调用的远程服务有很多,此时如果用户配置了路由规则(如制定某些方法调用某个特定节点),那么还会根据路由规则将Invoker列表过滤一遍.
然后,可选择的Invoker可能还会有很多,决定要调用哪一个的话要通过LoadBalance方法做负载均衡,最终选出一个拿来调用的Invoker.这个Invoker在调用之前优惠经过一个过滤器链,这个过滤器链通常是处理上下文,限流,计数等.
接着,会使用Client做数据传输,如我们常见的Netty Client等.传输之前肯定要做一些私有协议的构造,此时就会用到Codec接口.构造完成后,就会对数据包进行序列化,然后传输到服务提供者端.提供者接收到数据包,也会使用Codec处理协议头以及一些半包,粘包等.处理完成后再对完整的数据报文做反序列化处理.
随后,这个Request会被分配到ThreadPool中进行处理,Server会处理这些Request,根据请求查找对应的Expoter(它内部持有Invoker).Invoker是被装饰器模式一层一层套了非常多的Filter的,因此在调用最终的实现类之前,又会经过一个服务提供者的过滤连.
最终,我能得到了具体接口的真是实现并调用,再原路把结果返回.