什么是Dubbo?
Dubbo是一个分布式服务框架,以及SOA治理方案。其功能主要包括:高性能NIO通讯及多协议集成,服务动态寻址与路由,软负载均衡与容错,依赖分析与降级等。
Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合),我们可以非常容易地通过Dubbo来构建分布式服务,并根据自己实际业务应用场景来选择合适的集群容错模式,这个对于很多应用都是迫切希望的,只需要通过简单的配置就能够实现分布式服务调用,也就是说服务提供方(Provider)发布的服务可以天然就是集群服务。
为什么要用Dubbo?
随着服务化的进一步发展,服务之间的调用和依赖关系也越来越复杂,诞生了面向服务的框架体系(SOA),也因此衍生出了一系列相应的技术,如对服务提供、服务调用、连接处理、通性协议、序列号方式、服务发现、服务路由、日志输出等行为进行封装的服务框架。就这样分布式系统的服务治理的框架就出现了,Dubbo就这样产生了,它实现了面向接口代理的 RPC 调用,服务注册和发现,负载均衡,容错,扩展性等等功能。
什么事RPC?
RPC 其全称为 Remote Procedure Call 即远程过程调用。RPC 用于在远程计算机上调用函数过程(通常也可以在同一台机器上的进程之间使用它)。假设这个场景:服务 A、B 两个服务分别部署在两台服务器上,服务 A 需要调用服务 B 上的某个方法,此时因为这是在两台不同的服务器部署的服务,因此需要通过建立网络连接进行交互的这一过程就叫远程服务调用。
下图展示常见的两种 RPC 调用方式:
RPC 跨进程调用:即在相同操作系统中不同进程间的服务调用
PRC 跨系统且跨进程调用:即在不同操作系统间且跨进程远程服务调用
Dubbo的整体架构设计有哪些分层?
- 接口服务层(Service):与业务逻辑相关,根据provider和consumer的业务设计对应的接口和实现。
- 配置层(Config):用来初始化配置信息,用来管理Dubbo的配置。
- 服务代理层(Proxy):服务接口透明代理,provider和consumer都会生成Proxy,它用来调用远程接口。生成服务的客户端Stub和服务端的Skeleton,以ServiceProxy为中心,扩展接口为ProxyFactory。
- 服务注册层(Registry):封装服务地址的注册和发现,以URL为中心,扩展接口为RegistryFactory、Resitry、RegistryService。
- 路由层(Cluster):封装多个提供者的路由和负载均衡,并桥接注册中心,扩展接口为 Cluster、Directory、Router 和 LoadBlancce。
- 监控层(Monitor):PRC调用次数和调用时间监控,以Statistics为中心,扩展接口为 MonitorFactory、Monitor 和 MonitorService。
- 远程调用层(Protocol):封装RPC调用的具体过程,以 Invocation 和 Result 为中心,扩展接口为 Protocal、Invoker 和 Exporter。
- 信息交换层(Exchange):封装请求响应模式,同步转异步,以 Request 和Response 为中心,扩展接口为 Exchanger、ExchangeChannel、ExchangeClient 和 ExchangeServer。
- 网络传输层(Transport):将网络传输封装成统一接口,可以在这之上扩展更多的网络传输方式,扩展接口为 Channel、Transporter、Client、Server 和 Codec。
- 数据序列层(Serialize): 负责网络传输的序列化和反序列化,扩展接口为 Serialization、ObjectInput、ObjectOutput 和 ThreadPool。
Dubbo里面有哪几种节点角色?
节点 | 角色说明 |
Provider | 暴露服务的服务提供方 |
Consumer | 调用远程服务的服务消费方 |
Registry | 服务注册与发现的注册中心 |
Monitor | 统计服务的调用次数和调用时间的监控中心 |
Container | 服务运行容器 |
Dubbo服务注册与发现流程?
- 服务容器Container负责启动,加载,运行服务提供者。
- 服务提供者Provider在启动时,向注册中心注册自己提供的服务。
- 服务消费者Consumer在启动时,向注册中心订阅自己所需的服务。
- 注册中心Registry返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
- 服务消费者Consumer,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
- 服务消费者Consumer和提供者Provider,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心Monitor。
什么事Dubbo的SPI机制
- SPI(Service Provider Interface) 机制被大量用在开源项目中(比如Dubbo,SpringBoot...),它可以帮助我们进行功能扩展。
- SPI 的具体原理是这样的:我们将接口的实现类放在配置文件中,我们在程序运行过程中读取配置文件,通过反射加载实现类。这样,我们可以在运行的时候,动态替换接口的实现类。
- 一些配置类就可以使用SPI进行加载,如果我们需要进行扩展,就自定义类放在指定文件夹下。
- Java 本身就提供了 SPI 机制的实现。不过,Dubbo 没有直接用,而是对 Java 原生的 SPI 机制进行了增强,以便更好满足自己的需求。
为什么Dubbo不用JDK的SPI,而是要自己实现?
- 因为 Java SPI 在查找扩展实现类的时候遍历 SPI 的配置文件并且将实现类全部实例化,假设一个实现类初始化过程比较消耗资源且耗时,但是你的代码里面又用不上它,这就产生了资源的浪费。
- 因此 Dubbo 就自己实现了一个 SPI,给每个实现类配了个名字,通过名字去文件里面找到对应的实现类全限定名然后加载实例化,按需加载。
Dubbo支持哪些协议,他们的优缺点都有哪些?
1、 Dubbo协议:Dubbo默认使用Dubbo协议。
- 适合大并发小数据量的服务调用,以及服务消费者远大于提供者的情况Hessian二进制序列化。
- 缺点是不适合传送大数据包的服务。
2、rmi协议:采用JDK标准的rmi协议实现,传输参数和返回参数对象需要实现Serializable接口。使用java标准序列化机制,使用阻塞式短连接,传输数据包不限,消费者和提供者个数相当。
- 多个短连接,TCP协议传输,同步传输,适用常规的远程服务调用和rmi互操作
- 缺点:在依赖低版本的Common-Collections包,java反序列化存在安全漏洞,需升级commons-collections3 到3.2.2版本或commons-collections4到4.1版本。
3、 webservice协议:基于WebService的远程调用协议(Apache CXF的frontend-simple和transports-http)实现,提供和原生WebService的互操作多个短连接,基于HTTP传输,同步传输,适用系统集成和跨语言调用。
4、http协议:基于Http表单提交的远程调用协议,使用Spring的HttpInvoke实现。对传输数据包不限,传入参数大小混合,提供者个数多于消费者。
- 缺点是不支持传文件,只适用于同时给应用程序和浏览器JS调用
5、hessian:集成Hessian服务,基于底层Http通讯,采用Servlet暴露服务,Dubbo内嵌Jetty作为服务器实现,可与Hession服务互操作 通讯效率高于WebService和Java自带的序列化。
- 适用于传输大数据包(可传文件),提供者比消费者个数多,提供者压力较大
- 缺点是参数及返回值需实现Serializable接口,自定义实现List、Map、Number、Date、Calendar等接口
6、thrift协议:对thrift原生协议的扩展添加了额外的头信息。使用较少,不支持传null值
7、memcache:基于memcached实现的RPC协议
8、redis:基于redis实现的RPC协议
原理解析
ConfigServer
配置中心,和每个Server/Client之间会作一个实时的心跳检测(因为它们都是建立的Socket长连接),比如几秒钟检测一次。收集每个Server提供的服务的信息,每个Client的信息,整理出一个服务列表
当某个Server不可用,那么就更新受影响的服务对应的serverAddressList,即把这个Server从serverAddressList中踢出去(从地址列表中删除),同时将推送serverAddressList给这些受影响的服务的clientAddressList里面的所有Client。如:192.168.0.3挂了,那么UserService和ProductService的serverAddressList都要把192.168.0.3删除掉,同时把新的列表告诉对应的Client 172.16.0.1,172.16.0.2,172.16.0.3;
当某个Client挂了,那么更新受影响的服务对应的clientAddressList ConfigServer根据服务列表,就能提供一个web管理界面,来查看管理服务的提供者和使用者。 新加一个Server时,由于它会主动与ConfigServer取得联系,而ConfigServer又会将这个信息主动发送给Client,所以新加一个Server时,只需要启动Server,然后几秒钟内,Client就会使用上它提供的服务
Client
调用服务的机器,每个Client启动时,主动与ConfigServer建立Socket长连接,并将自己的IP等相应信息发送给ConfigServer。 Client在使用服务的时候根据服务名称去ConfigServer中获取服务提供者信息(这样ConfigServer就知道某个服务是当前哪几个Client在使用),Client拿到这些服务提供者信息后,与它们都建立连接,后面就可以直接调用服务了,当有多个服务提供者的时候,Client根据一定的规则来进行负载均衡,如轮询,随机,按权重等。
一旦Client使用的服务它对应的服务提供者有变化(服务提供者有新增,删除的情况),ConfigServer就会把最新的服务提供者列表推送给Client,Client就会依据最新的服务提供者列表重新建立连接,新增的提供者建立连接,删除的提供者丢弃连接
Server
真正提供服务的机器,每个Server启动时,主动与ConfigServer建立Scoket长连接,并将自己的IP,提供的服务名称,端口等信息直接发送给ConfigServer,ConfigServer就会收集到每个Server提供的服务的信息。
Dubbo和SpringCloud有什么区别?
最大区别:
- Dubbo是高性能和透明化的RPC远程服务调用框架,也是SOA服务治理方案。
- SpringCloud不是一个开发框架,而是一整套的分布式微服务解决方案。
- Dubbo底层是使用Netty这样的NIO框架,是基于TCP协议传输的,是二进制传输的,占用带宽较少,配合以Hession序列化完成RPC通信。
- SpringCloud是基于Http协议+rest接口调用远程过程的通信,相对来说,Http请求会有更大的报文,占的带宽也会更多。但是REST相比RPC更为灵活,服务提供方和调用方的依赖只依靠一纸契约,不存在代码级别的强依赖,这在强调快速演化的微服务环境下,显得更为合适,至于注重通信速度还是方便灵活性,具体情况具体考虑。
模块区别:
- Dubbo主要分为服务注册中心,服务提供者,服务消费者,还有管控中心。
- SpringCloud则是一个完整的分布式一站式框架,他有着一样的服务注册中心,服务提供者,服务消费者,管控台,断路器,分布式配置服务,消息总线,以及服务追踪等。
总结
以上就是Dubbo RPC的核心流程逻辑了,这次研究时有很多逻辑被我当做了黑盒来处理,比如扩展点加载、负载均衡、网络请求、线程模型等……实际上一次RPC过程远比上述描述的复杂,按照官网的说明,RPC过程的流程如下所示: