Dubbo理论知识

本文是做者根据官方文档以及本身平时的使用状况,对 Dubbo 所作的一个总结。若是不懂 Dubbo 的使用的话,能够参考个人这篇文章《超详细,新手都能看懂 !使用SpringBoot+Dubbo 搭建一个简单的分布式服务》html

Dubbo 官网:http://dubbo.apache.org/zh-cn/index.htmlvue

Dubbo 中文文档: http://dubbo.apache.org/zh-cn/index.htmljava

一 重要的概念

1.1 什么是 Dubbo?

Apache Dubbo (incubating) |ˈdʌbəʊ| 是一款高性能、轻量级的开源Java RPC 框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。简单来讲 Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。node

Dubbo 目前已经有接近 23k 的 Star ,Dubbo的Github 地址:https://github.com/apache/incubator-dubbo 。 另外,在开源中国举行的2018年度最受欢迎中国开源软件这个活动的评选中,Dubbo 更是凭借其超高人气仅次于 vue.js 和 ECharts 得到第三名的好成绩。git

Dubbo 是由阿里开源,后来加入了 Apache 。正式因为 Dubbo 的出现,才使得愈来愈多的公司开始使用以及接受分布式架构。github

咱们上面说了 Dubbo 其实是 RPC 框架,那么什么是 RPC呢?面试

1.2 什么是 RPC?RPC原理是什么?

什么是 RPC?算法

RPC(Remote Procedure Call)—远程过程调用,它是一种经过网络从远程计算机程序上请求服务,而不须要了解底层网络技术的协议。好比两个不一样的服务 A、B 部署在两台不一样的机器上,那么服务 A 若是想要调用服务 B 中的某个方法该怎么办呢?使用 HTTP请求 固然能够,可是可能会比较慢并且一些优化作的并很差。 RPC 的出现就是为了解决这个问题。数据库

RPC原理是什么?apache

我这里这是简单的提一下。详细内容能够查看下面这篇文章:

http://www.importnew.com/22003.html

RPC原理图

  1. 服务消费方(client)调用以本地调用方式调用服务;
  2. client stub接收到调用后负责将方法、参数等组装成可以进行网络传输的消息体;
  3. client stub找到服务地址,并将消息发送到服务端;
  4. server stub收到消息后进行解码;
  5. server stub根据解码结果调用本地的服务;
  6. 本地服务执行并将结果返回给server stub;
  7. server stub将返回结果打包成消息并发送至消费方;
  8. client stub接收到消息,并进行解码;
  9. 服务消费方获得最终结果。

下面再贴一个网上的时序图:

RPC原理时序图

说了这么多,咱们为何要用 Dubbo 呢?

1.3 为何要用 Dubbo?

Dubbo 的诞生和 SOA 分布式架构的流行有着莫大的关系。SOA 面向服务的架构(Service Oriented Architecture),也就是把工程按照业务逻辑拆分红服务层、表现层两个工程。服务层中包含业务逻辑,只须要对外提供服务便可。表现层只须要处理和页面的交互,业务逻辑都是调用服务层的服务来实现。SOA架构中有两个主要角色:服务提供者(Provider)和服务使用者(Consumer)。

为何要用 Dubbo

若是你要开发分布式程序,你也能够直接基于 HTTP 接口进行通讯,可是为何要用 Dubbo呢?

我以为主要能够从 Dubbo 提供的下面四点特性来讲为何要用 Dubbo:

  1. 负载均衡——同一个服务部署在不一样的机器时该调用那一台机器上的服务。
  2. 服务调用链路生成——随着系统的发展,服务愈来愈多,服务间依赖关系变得错踪复杂,甚至分不清哪一个应用要在哪一个应用以前启动,架构师都不能完整的描述应用的架构关系。Dubbo 能够为咱们解决服务之间互相是如何调用的。
  3. 服务访问压力以及时长统计、资源调度和治理——基于访问压力实时管理集群容量,提升集群利用率。
  4. 服务降级——某个服务挂掉以后调用备用服务。

另外,Dubbo 除了可以应用在分布式系统中,也能够应用在如今比较火的微服务系统中。不过,因为 Spring Cloud 在微服务中应用更加普遍,因此,我以为通常咱们提 Dubbo 的话,大部分是分布式系统的状况。

咱们刚刚提到了分布式这个概念,下面再给你们介绍一下什么是分布式?为何要分布式?

1.4 什么是分布式?

分布式或者说 SOA 分布式重要的就是面向服务,说简单的分布式就是咱们把整个系统拆分红不一样的服务而后将这些服务放在不一样的服务器上减轻单体服务的压力提升并发量和性能。好比电商系统能够简单地拆分红订单系统、商品系统、登陆系统等等,拆分以后的每一个服务能够部署在不一样的机器上,若是某一个服务的访问量比较大的话也能够将这个服务同时部署在多台机器上。

1.5 为何要分布式?

从开发角度来说单体应用的代码都集中在一块儿,而分布式系统的代码根据业务被拆分。因此,每一个团队能够负责一个服务的开发,这样提高了开发效率。另外,代码根据业务拆分以后更加便于维护和扩展。

另外,我以为将系统拆分红分布式以后不光便于系统扩展和维护,更能提升整个系统的性能。你想想嘛?把整个系统拆分红不一样的服务/系统,而后每一个服务/系统 单独部署在一台服务器上,是否是很大程度上提升了系统性能呢?

二 Dubbo 的架构

2.1 Dubbo 的架构图解

Dubbo 架构

上述节点简单说明:

  • Provider: 暴露服务的服务提供方
  • Consumer: 调用远程服务的服务消费方
  • Registry: 服务注册与发现的注册中心
  • Monitor: 统计服务的调用次数和调用时间的监控中心
  • Container: 服务运行容器

调用关系说明:

  1. 服务容器负责启动,加载,运行服务提供者。
  2. 服务提供者在启动时,向注册中心注册本身提供的服务。
  3. 服务消费者在启动时,向注册中心订阅本身所需的服务。
  4. 注册中心返回服务提供者地址列表给消费者,若是有变动,注册中心将基于长链接推送变动数据给消费者。
  5. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,若是调用失败,再选另外一台调用。
  6. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

重要知识点总结:

  • 注册中心负责服务地址的注册与查找,至关于目录服务,服务提供者和消费者只在启动时与注册中心交互,注册中心不转发请求,压力较小
  • 监控中心负责统计各服务调用次数,调用时间等,统计先在内存汇总后每分钟一次发送到监控中心服务器,并以报表展现
  • 注册中心,服务提供者,服务消费者三者之间均为长链接,监控中心除外
  • 注册中心经过长链接感知服务提供者的存在,服务提供者宕机,注册中心将当即推送事件通知消费者
  • 注册中心和监控中心所有宕机,不影响已运行的提供者和消费者,消费者在本地缓存了提供者列表
  • 注册中心和监控中心都是可选的,服务消费者能够直连服务提供者
  • 服务提供者无状态,任意一台宕掉后,不影响使用
  • 服务提供者所有宕掉后,服务消费者应用将没法使用,并没有限次重连等待服务提供者恢复

2.2 Dubbo 工做原理

Dubbo 工做原理

图中从下至上分为十层,各层均为单向依赖,右边的黑色箭头表明层之间的依赖关系,每一层均可以剥离上层被复用,其中,Service 和 Config 层为 API,其它各层均为 SPI。

各层说明:

  • 第一层:service层,接口层,给服务提供者和消费者来实现的
  • 第二层:config层,配置层,主要是对dubbo进行各类配置的
  • 第三层:proxy层,服务接口透明代理,生成服务的客户端 Stub 和服务器端 Skeleton
  • 第四层:registry层,服务注册层,负责服务的注册与发现
  • 第五层:cluster层,集群层,封装多个服务提供者的路由以及负载均衡,将多个实例组合成一个服务
  • 第六层:monitor层,监控层,对rpc接口的调用次数和调用时间进行监控
  • 第七层:protocol层,远程调用层,封装rpc调用
  • 第八层:exchange层,信息交换层,封装请求响应模式,同步转异步
  • 第九层:transport层,网络传输层,抽象mina和netty为统一接口
  • 第十层:serialize层,数据序列化层,网络传输须要

三 Dubbo 的负载均衡策略

3.1 先来解释一下什么是负载均衡

先来个官方的解释。

维基百科对负载均衡的定义:负载均衡改善了跨多个计算资源(例如计算机,计算机集群,网络连接,中央处理单元或磁盘驱动的的工做负载分布。负载平衡旨在优化资源使用,最大化吞吐量,最小化响应时间,并避免任何单个资源的过载。使用具备负载平衡而不是单个组件的多个组件能够经过冗余提升可靠性和可用性。负载平衡一般涉及专用软件或硬件。

上面讲的你们可能不太好理解,再用通俗的话给你们说一下。

好比咱们的系统中的某个服务的访问量特别大,咱们将这个服务部署在了多台服务器上,当客户端发起请求的时候,多台服务器均可以处理这个请求。那么,如何正确选择处理该请求的服务器就很关键。假如,你就要一台服务器来处理该服务的请求,那该服务部署在多台服务器的意义就不复存在了。负载均衡就是为了不单个服务器响应同一请求,容易形成服务器宕机、崩溃等问题,咱们从负载均衡的这四个字就能明显感觉到它的意义。

3.2 再来看看 Dubbo 提供的负载均衡策略

在集群负载均衡时,Dubbo 提供了多种均衡策略,默认为 random 随机调用。能够自行扩展负载均衡策略,参见:负载均衡扩展

备注:下面的图片来自于:尚硅谷2018Dubbo 视频。

3.2.1 Random LoadBalance(默认,基于权重的随机负载均衡机制)

  • 随机,按权重设置随机几率。
  • 在一个截面上碰撞的几率高,但调用量越大分布越均匀,并且按几率使用权重后也比较均匀,有利于动态调整提供者权重。

基于权重的随机负载均衡机制

3.2.2 RoundRobin LoadBalance(不推荐,基于权重的轮询负载均衡机制)

  • 轮循,按公约后的权重设置轮循比率。
  • 存在慢的提供者累积请求的问题,好比:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,长此以往,全部请求都卡在调到第二台上。

基于权重的轮询负载均衡机制

3.2.3 LeastActive LoadBalance

  • 最少活跃调用数,相同活跃数的随机,活跃数指调用先后计数差。
  • 使慢的提供者收到更少请求,由于越慢的提供者的调用先后计数差会越大。

3.2.4 ConsistentHash LoadBalance

  • 一致性 Hash,相同参数的请求老是发到同一提供者。(若是你须要的不是随机负载均衡,是要一类请求都到一个节点,那就走这个一致性hash策略。)
  • 当某一台提供者挂时,本来发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引发剧烈变更。
  • 算法参见:http://en.wikipedia.org/wiki/Consistent_hashing
  • 缺省只对第一个参数 Hash,若是要修改,请配置 <dubbo:parameter key="hash.arguments" value="0,1" />
  • 缺省用 160 份虚拟节点,若是要修改,请配置 <dubbo:parameter key="hash.nodes" value="320" />

3.3 配置方式

xml 配置方式

服务端服务级别

<dubbo:service interface="..." loadbalance="roundrobin" />

客户端服务级别

<dubbo:reference interface="..." loadbalance="roundrobin" />

服务端方法级别

<dubbo:service interface="..."> <dubbo:method name="..." loadbalance="roundrobin"/> </dubbo:service>

客户端方法级别

<dubbo:reference interface="..."> <dubbo:method name="..." loadbalance="roundrobin"/> </dubbo:reference>

注解配置方式:

消费方基于基于注解的服务级别配置方式:

@Reference(loadbalance = "roundrobin") HelloService helloService;

四 zookeeper宕机与dubbo直连的状况

zookeeper宕机与dubbo直连的状况在面试中可能会被常常问到,因此要引发重视。

在实际生产中,假如zookeeper注册中心宕掉,一段时间内服务消费方仍是可以调用提供方的服务的,实际上它使用的本地缓存进行通信,这只是dubbo健壮性的一种提现。

dubbo的健壮性表现:

  1. 监控中心宕掉不影响使用,只是丢失部分采样数据
  2. 数据库宕掉后,注册中心仍能经过缓存提供服务列表查询,但不能注册新服务
  3. 注册中心对等集群,任意一台宕掉后,将自动切换到另外一台
  4. 注册中心所有宕掉后,服务提供者和服务消费者仍能经过本地缓存通信
  5. 服务提供者无状态,任意一台宕掉后,不影响使用
  6. 服务提供者所有宕掉后,服务消费者应用将没法使用,并没有限次重连等待服务提供者恢复

咱们前面提到过:注册中心负责服务地址的注册与查找,至关于目录服务,服务提供者和消费者只在启动时与注册中心交互,注册中心不转发请求,压力较小。因此,咱们能够彻底能够绕过注册中心——采用 dubbo 直连 ,即在服务消费方配置服务提供方的位置信息。

xml配置方式:

<dubbo:reference id="userService" interface="com.zang.gmall.service.UserService" url="dubbo://localhost:20880" />

注解方式:

 @Reference(url = "127.0.0.1:20880") HelloService helloService;
相关文章
相关标签/搜索