深入理解Dubbo与实战 - 1. 架构

1. Dubbo 高性能 RPC框架

1.1 架构

  1. 服务容器负责启动,加载,运行服务提供者。
  2. 服务提供者在启动时,向注册中心注册自己提供的服务。
  3. 服务消费者在启动时,向注册中心订阅自己所需的服务。
  4. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
  5. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
  6. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
    深入理解Dubbo与实战 - 1. 架构_第1张图片

1.2 总体分层

Dubbo 总体分为业务层、RPC层、Remote 三层。
深入理解Dubbo与实战 - 1. 架构_第2张图片
Service和Config两层可以认为是API层,主要提供给API使用者,使用者无须关心底层
的实现,只需要配置和完成业务代码即可;后面所有的层级合在一起,可以认为是SPI层,主要提供给扩展者使用,即用户可以基于Dubb。框架做定制性的二次开发,扩展其功能。

层次名 层次名 作用
Service 业务层 开发者实现的业务代码
Config 配置层 要围绕ServiceConfig (暴露的服务配置)和ReferenceConfig (引用的服务配置)两个实现类展开,初始化配置信息。可以理解为该层管理了整个Dubbo的配置
Proxy 服务代理层 在Dubbo中,无论生产者还是消费者,框架都会生成一个代理类,整个过程对上层是透明的。当调用一个远程接口时,看起来就像是调用了一个本地的接口一样,代理层会自动做远程调用并返回结果,即让业务层对远程调用完全无感
Registry 注册层 负责服务的注册与发现
Cluster 集群容错层 该层主要负责:远程调用失败时的容错策略(如失败重试、快速失败);选择具体调用节点时的负载均衡策略(如随机、一致性Hash等);特殊调用路径的路由策略(如某个消费者只会调用某个IP的生产者)
Monitor 监控层 监控统计调用次数和调用时间
Protocol 远程调用层 封装RPC调用具体过程,Protocol是Invoker暴露(发布一个服务让别人可以调用)和引用(引用一个远程服务到本地)的主功能入口,它负责管理Invoker的整个生命周期。Invoker是Dubbo的核心模型,框架中所有其他模型都向它靠拢,或者转换成它,它代表一个可执行体。允许向它发起invoke调用,它可能是执行一个本地的接口实现,也可能是一个远程的实现,还可能一个集群实现
Exchange 信息交换层 建立Request-Response模型,封装请求响应模式,如把同步请求转化为异步请求
Transport 网络传输层 把网络传输抽象为统一的接口,如Mina和Netty虽然接口不一样,但是Dubbo在它们上面又封装了统一的接口。用户也可以根据其扩展接口添加更多的网络传输方式
Serialize 序列化层 序列化层。如果数据要通过网络进行发送,则需要先做序列化,变成二进制流。序列化层负责管理整个框架网络传输时的序列化/反序列化工作

1.3 调用过程深入理解Dubbo与实战 - 1. 架构_第3张图片

服务暴露过程:
首先,服务器端(服务提供者)在框架启动时,会初始化服务实例,通过Proxy组件调用具体协议(Protocol ),把服务端要暴露的接口封装成Invoker (真实类型是
AbstractProxylnvoker),然后转换成Exporter,这个时候框架会打开服务端口等并记录服务实例到内存中,最后通过Registry把服务元数据注册到注册中心。

  • Proxy组件:我们知道,Dubbo中只需要引用一个接口就可以调用远程的服务,并且只需要像调用本地方法一样调用即可。其实是Dubbo框架为我们生成了代理类,调用的方法其实是Proxy组件生成的代理方法,会自动发起远程/本地调用,并返回结果,整个过程对用户完全透明。
  • Protocol:顾名思义,协议就是对数据格式的一种约定。它可以把我们对接口的配置,根据不同的协议转换成不同的Invoker对象。例如:用DubboProtocol可以把XML文件中一个远程接口的配置转换成一个Dubbolnvoker.
  • Exporter:用于暴露到注册中心的对象,它的内部属性持有了 Invoker对象,我们可以认为它在Invoker上包了 一层。
  • Registry:把Exporter注册到注册中心。

消费者调用过程

  • 首先,调用过程也是从一个Proxy开始的,Proxy持有了一个Invoker对象。然后触发invoke调用。
  • 在invoke调用过程中,需要使用Cluster处理容错。Cluster在调用之前会通过Directory获取所有可以调用的远程服务Invoker列表(一个接口可能有多个节点提供服务)。由于可以调用的远程服务有很多,此时如果用户配置了路由规则,那么还会根据路由规则将Invoker列表过滤一遍。继续通过LoadBalance方法做负载均衡,最终选出一个可以调用的Invoker。
  • 这个Invoker在调用之前又会经过一个过滤器链,这个过滤器链通常是处理上下文、限流、计数等。
  • 接着,会使用Client做数据传输,如我们常见的Netty Client等。传输之前肯定要做一些私有协议的构造,此时就会用到Codec接口。构造完成后,就对数据包做序列化(Serialization),然后传输到服务提供者端。服务提供者收到数据包,也会使用Codec处理协议头及一些半包、
    粘包等。处理完成后再对完整的数据报文做反序列化处理。
  • 随后,这个Request会被分配到线程池(ThreadPool)中进行处理Server会处理这些Request,根据请求查找对应的Exporter (它内部持有了 Invoker。Invoker是被用装饰器模式一层一层套了非常多Filter的,因此在调用最终的实现类之前,又会经过一个服务提供者端的过滤器链。
  • 最终,我们得到了具体接口的真实实现并调用,再原路把结果返回。

你可能感兴趣的:(Dubbo,rpc,java,网络,分布式)