Dubbo的配置过程,实现原理及架构详解
一. Dubbo是什么?Dubbo能做什么?
随着互联网的发展,市场需求快速变更,业务持续高速增长,网站早已从单一应用架构演变为分布式服务架构及流动计算架构。在分布式架构的背景下,在本地调用非本进程内(远程)的资源就变得在所难免。因此,后期涌现出了很多RPC(远程过程调用)的框架,如 Apache Thrift、Hessian、gRPC 等。然而,随着 RPC 框架的推广和使用的日益深入,服务越来越多的情况也衍生出了新的业务需求:
(1)如何管理过多的服务URL
(2)消费者要想使用服务,就必须直接知道和了解服务提供方的服务地址。后台服务地址一旦改变,则需要一一通知消费者,这种高度耦合的关系很不利用维护。
(3)海量的服务会延伸出很多的错误,如何对这些常见失败案例提供服务治理的功能。
在这个背景下,阿里巴巴集团推出了Dubbo分布式框架,来解决和缓和目前RPC框架下的这些需求和瓶颈。具体措施如下:
(1)通过引入服务注册中心Registry来管理服务的依赖关系,并通过在消费方获取服务提供方地址列表,实现软负载均衡和 Failover,降低对 F5 硬件负载均衡器的依赖。
(2)在注册中心提供订阅发布机制,使得消费者只需要关心服务本身,而不再需要写死服务提供方地址。注册中心基于接口名查询服务提供者的ip地址,然后将服务提供方的地址动态的回传给服务消费者。
(3)专门独立出一个服务治理中心,统一对集群各节点的服务做在线治理,提升治理效率.
二. Dubbo 的工作原理(参照官方文档:https://github.com/apache/dubbo)
1) 节点说明:
Provider:暴露服务的服务提供方
Consumer:调用远程服务的服务消费方
Registry:服务注册与发现的注册中心
Monitor: 统计服务的调用次数和调用时间的监控中心
Container:服务运行容器
2) 调用过程及工作原理:
0. 服务容器Container启动,加载,运行服务提供者,通过 main 函数初始化 Spring 上下文,根据服务提供者的XML配置文件将每个服务按照指定的协议发布(每个服务都有自己对应的协议端口号protocol,port),从而完成多个服务的初始化工作。
1. 服务提供者Provider在启动时,根据配置的服务注册中心地址连接服务注册中心Registry,将服务提供者信息发布到注册中心(如zookeeper),向注册中心注册自己提供的服务(如上图)。
2. 服务消费者Consumer在启动时,消费者根据服务消费者XML配置文件的服务引用信息,连接到注册中心,向注册中心订阅自己所需的服务。
3. 服务注册中心根据消费者的服务订阅关系,返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送最新的服务地址信息给消费者(这个监听过程是由Dubbo另外提供的NotifyListrener辅助完成的,具体可以看下一节的介绍)。
4. 服务消费者调用远程服务时,根据路由策略,从本地缓存的服务提供者地址列表中选择选一台提供者进行,然后根据协议类型建立链路,跨进程调用服务提供者,如果调用失败,再选另一台调用。
5. 服务消费者Consumer和提供者Provider,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心Monitor。
三.Dubbo的底层架构解读(参考文档:http://dubbo.apache.org/zh-cn/docs/dev/design.html)
(1)从图上前两层,我们可以很容易的分析出左边蓝色部分是服务消费者(ReferenceConfig),右边是服务提供者(implement接口,ServiceConfig)。
(2)其中在左边的接口表示是扩展给消费者单独使用的,右边的接口表示是扩展给服务者单独使用的。而中间的接口是服务者和消费者两者都可以使用的。
(3)从上到下按照dubbo的工作过程,一共分为10层。各部分的介绍参照(http://crazyfzw.github.io/2018/06/10/dubbo-architecture/)
-
服务接口层(Service):该层是与实际业务逻辑相关的,根据服务提供方和服务消费方的业务设计对应的接口和实现。
-
配置层(Config):对外配置接口,以 ServiceConfig 和 ReferenceConfig 为中心,可以直接 new 配置类,也可以通过 spring 解析配置生成配置类。
-
服务代理层(Proxy):服务接口透明代理,生成服务的客户端 Stub 和服务器端 Skeleton,以 ServiceProxy 为中心,扩展接口为 ProxyFactory。
-
服务注册层(Registry):封装服务地址的注册与发现,以服务URL为中心,扩展接口为 RegistryFactory、Registry 和 RegistryService。可能没有服务注册中心,此时服务提供方直接暴露服务。
-
集群层(Cluster):封装多个提供者的路由及负载均衡,并桥接注册中心,以Invoker为中心,扩展接口为 Cluster、Directory、Router 和 LoadBalance。将多个服务提供方组合为一个服务提供方,实现对服务消费方来透明,只需要与一个服务提供方进行交互。
-
监控层(Monitor):RPC 调用次数和调用时间监控,以 Statistics 为中心,扩展接口为 MonitorFactory、Monitor 和 MonitorService。
-
远程调用层(Protocol):封将 RPC 调用,以 Invocation 和 Result 为中心,扩展接口为 Protocol、Invoker 和 Exporter。Protocol 是服务域,它是 Invoker 暴露和引用的主功能入口,它负责 Invoker 的生命周期管理。Invoker 是实体域,它是 Dubbo 的核心模型,其它模型都向它靠扰,或转换成它,它代表一个可执行体,可向它发起 invoke 调用,它有可能是一个本地的实现,也可能是一个远程的实现,也可能一个集群实现。
-
信息交换层(Exchange):封装请求响应模式,同步转异步,以 Request 和 Response 为中心,扩展接口为 Exchanger、ExchangeChannel、ExchangeClient 和 ExchangeServer。
-
网络传输层(Transport):抽象 mina 和 netty 为统一接口,以 Message 为中心,扩展接口为 Channel、Transporter、Client、Server 和 Codec。
-
数据序列化层(Serialize):可复用的一些工具,扩展接口为 Serialization、 ObjectInput、ObjectOutput和ThreadPool。
大致的工作流程是:
1.读取配置文件,生成代理对象
2.代理对象负责将其注册到注册中心进行备份
3.下层monitor层对双方进行业务监控。
在 RPC 中,Protocol 是核心层,也就是只要有 Protocol + Invoker + Exporter 就可以完成非透明的 RPC 调用,然后在 Invoker 的主过程上 Filter 拦截点。
需要注意的是:为了底层可以使用NIO来传输数据,所有的公共api接口都应该实现Serializable.
四.Dubbo的缺点
因为是阿里出品,所以其目前只支持Java语言,对语言的支持性不是很好。