Dubbo的基础知识

Dubbo的核心架构是怎样的?

  • Registry:注册中心。 负责服务地址的注册与查找,服务的 Provider 和 Consumer 只在启动时与注册中心交互。注册中心通过长连接感知 Provider 的存在,在 Provider 出现宕机的时候,注册中心会立即推送相关事件通知 Consumer;

  • Provider:服务提供者。 在它启动的时候,会向 Registry 进行注册操作,将自己服务的地址和相关配置信息封装成 URL 添加到 ZooKeeper 中;

  • Consumer

    :服务消费者。 在它启动的时候,会向 Registry 进行订阅操作。订阅操作会从 ZooKeeper 中获取 Provider 注册的 URL,并在 ZooKeeper 中添加相应的监听器。

    • 获取到 Provider URL 之后,Consumer 会根据负载均衡算法从多个 Provider 中选择一个 Provider 并与其建立连接,最后发起对 Provider 的 RPC 调用;
    • 如果 Provider URL 发生变更,Consumer 将会通过之前订阅过程中在注册中心添加的监听器,获取到最新的 Provider URL 信息,进行相应的调整,比如断开与宕机 Provider 的连接,并与新的 Provider 建立连接;
    • Consumer 与 Provider 建立的是长连接,且 Consumer 会缓存 Provider 信息,所以一旦连接建立,即使注册中心宕机,也不会影响已运行的 Provider 和 Consumer;
  • Monitor:监控中心。 用于统计服务的调用次数和调用时间。Provider 和 Consumer 在运行过程中,会在内存中统计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。监控中心在上面的架构图中并不是必要角色,监控中心宕机不会影响 Provider、Consumer 以及 Registry 的功能,只会丢失监控数据而已。

为什么说Dubbo是基于URL驱动的?

  • URL 在 Dubbo 中被当作是“公共的契约”。一个 URL 可以包含非常多的扩展点参数,URL 作为上下文信息贯穿整个扩展点设计体系;
  • Dubbo 基于 URL驱动的好处:
    • 统一数据格式规范,让交互变得简单化;
    • 使用URL作为方法参数,便于参数扩展,新参数只需要以k/v形式追加到URL即可,不需要改变入参或返回值的数据结构;

Dubbo的URL由哪些部分组成?

  • 下面是Provider 注册到 ZooKeeper 上的 URL 例子:

dubbo://172.17.32.91:20880/org.apache.dubbo.demo.DemoService ?anyhost=true&application=dubbo-demo-api-provider&dubbo=2.0.2 &interface=org.apache.dubbo.demo.DemoService&methods=sayHello,sayHelloAsync&pid=32508&release= &side=provider&timestamp=1593253404714dubbo://172.17.32.91:20880/org.apache.dubbo.demo.DemoService ?anyhost=true&application=dubbo-demo-api-provider&dubbo=2.0.2 &interface=org.apache.dubbo.demo.DemoService&methods=sayHello,sayHelloAsync &pid=32508&release=&side=provider&timestamp=1593253404714

  • protocol:dubbo 协议;
  • host/port:172.17.32.91:20880;
  • path:org.apache.dubbo.demo.DemoService;
  • parameters:参数键值对,这里是问号后面的参数。

相较于JDK SPI而言,Dubbo SPI做了哪些改进?

  • JDK SPI 会一次性实例化扩展点所有实现,如果有扩展实现初始化很耗时,但如果没用上也加载,会很浪费资源,而Dubbo SPI可以按需进行加载,实例化后会进行缓存;
  • Dubbo按照SPI配置文件的用途,将其分为了三个目录:
    • META-INF/services/:该目录下的 SPI 配置文件用来兼容 JDK SPI ;
    • META-INF/dubbo/:该目录用于存放用户自定义 SPI 配置文件;
    • META-INF/dubbo/internal/:该目录用于存放 Dubbo 内部使用的 SPI 配置文件。
  • Dubbo 将 SPI 配置文件改成了 KV 格式,key被称为扩展名,我们可以指定扩展名来查找具体的实现,从而实现按需加载;
  • 扩展名更利于我们排查异常,Dubbo SPI在抛出异常时,会携带扩展名信息,而不是简单提升具体实现类无法加载,提升我们排查问题的效率。

Dubbo的扩展点有哪些分类?

  • 普通扩展类:最基础的,配置在SPI配置文件中的扩展类实现;
  • 包装扩展类:Wrapper类是一种装饰者模式,在构造方法中传入一个具体扩展接口的实现,属于Dubbo的自动包装特性。在ExtensionLoader在加载扩展时,如果发现这个扩展类包含其它扩展点作为构造函数参数,则这个扩展类就会被认定为是Wrapper类;
  • 自适应扩展类:一个扩展接口会有多种实现类,具体使用哪个实现类可以不写死在配置或代码中,在运行时,通过传入URL中的某些参数动态确定,这属于扩展点的自适应特性。

Dubbo的@Adaptive注解与@Activate注解的区别是什么?

  • @Adaptive称为自适应扩展点注解。自适应扩展指的是,一个扩展接口往往会有多种实现类,因为Dubbo是基于URL驱动,所以在运行时,通过传入URL中的某些参数来动态控制具体实现;

    • @Adaptive可以修饰类级别与方法级别:

      • 修饰方法级别时,Dubbo初始化扩展点时会自动生成和编译一个动态的Adaptive类,是一种动态代理的模式,方法里会有一些抽象的通用逻辑,根据解析URL得到的信息,找到并调用真正的实现类;
      • 修饰类级别时,省略了生成动态代理类的过程,由该类中决定具体实现,可理解为是一种静态代理的模式。另外对于同一个扩展点,类级别的Adaptive只能有一个。
  • @Activate称为自动激活扩展点注解。主要使用在有多个扩展点实现、需要同时根据不同条件被激活的场景中,如Filter需要多个同时激活,因为每个Filter实现的是不同的功能;
    • @Activate的参数:
参数名 效果
String[] group() URL中的分组如果匹配则激活
String[] value() URL中如果包含该key值,则会激活
String[] before() 填写扩展点列表,表示哪些扩展点要在本扩展点之前激活
String[] after() 表示哪些扩展点需要在本扩展点之后激活
int order() 排序信息

服务通信

如何设计一个rpc框架?

  • 主要的模块:

    • protocol:简易版 RPC 框架的自定义协议;
    • serialization:提供了自定义协议对应的序列化、反序列化的相关工具类;
    • codec:提供了自定义协议对应的编码器和解码器;
    • transport:基于 Netty 提供了底层网络通信的功能,其中会使用到 codec 包中定义编码器和解码器,以及 serialization 包中的序列化器和反序列化器;
    • registry:基于 ZooKeeper 和 Curator 实现了简易版本的注册中心功能;
    • proxy:使用 JDK 动态代理实现了一层代理。

一次rpc请求的流程是怎样的?

  • Client 首先会调用本地的代理,也就是图中的 Proxy;
  • Client 端 Proxy 会按照协议(Protocol),将调用中传入的数据序列化成字节流;
  • 之后 Client 会通过网络,将字节数据发送到 Server 端;
  • Server 端接收到字节数据之后,会按照协议进行反序列化,得到相应的请求信息;
  • Server 端 Proxy 会根据序列化后的请求信息,调用相应的业务逻辑;
  • Server 端业务逻辑的返回值,也会按照上述逻辑返回给 Client 端。

序列化的意义是什么?

  • 简单来说,序列化是把对象的状态信息转化为可存储或传输的形式过程,也就是把对象转化为字节序列的过程称为对象的序列化。反序列化是序列化的逆向过程,把字节数组反序列化为对象。

Dubbo服务发布的流程是怎样的?

  • dubbo的service本质是一个被Spring管理的ServiceBean,ServiceBean实现了众多Spring提供的接口;

    • afterPropertiesSet:解析配置;
    • onApplicationEvent:执行发布流程;
  • 服务发布流程:
  1. 基于Spring进行配置解析,将配置属性转换成ServiceBean对象;
  2. 各种判断校验逻辑,保证信息的安全;
  3. 组装URL(registry://、dubbo://、injvm://);
  4. 构建invoker对象;
  5. RegistryProtocol.export(向注册中心注册URL);
  6. 各种wrapper的增强(gos、listener、filter链);
  7. DubboProtocol.export(发布服务);
  8. 启动一个NettyServer。

Dubbo服务引用的流程是怎样的?

  • Dubbo 的 consumer 会通过 ReferenceBean 实现服务引用;
  • Dubbo 服务引用的时机有两个:
    • 第一个是在 Spring 容器调用 ReferenceBean 的 afterPropertiesSet 方法时引用服务;
    • 第二个是在 ReferenceBean 对应的服务被注入到其他类中时引用,而入口都是getObject方法。
  • 服务引用流程:
  1. 生成远程服务的代理;
  2. 通过注册中心获得目标服务的url地址;
  3. 实现远程网络通信;
  4. 实现负载均衡;
  5. 实现集群容错。

Dubbo的Invoker是什么?

  • Invoker 是Dubbo 的核心模型,其它模型都向它靠拢,或转换成它,它代表一个可执行体,可向它发起 invoke 调用,它有可能是一个本地的实现,也可能是一个远程的实现,也可能一个集群实现;
  • 在服务提供方,Invoker 用于调用服务提供类。在服务消费方,Invoker 用于执行远程调用。Invoker 是由 Protocol 实现类构建而来。

在Dubbo中Proxy 和 Wrapper的作用是什么?

  • Consumer 端的 Proxy 底层屏蔽了复杂的网络交互、集群策略以及 Dubbo 内部的 Invoker 等概念,提供给上层使用的是业务接口;
  • Provider 端的 Wrapper 是将个性化的业务接口实现,统一转换成 Dubbo 内部的 Invoker 接口实现;
  • 正是由于 Proxy 和 Wrapper 这两个组件的存在,Dubbo 才能实现内部接口和业务接口的无缝转换。

集群

Dubbo的Directory(服务目录)是什么?

  • Directory中存储了一些和服务提供者有关的信息,通过Directory,服务消费者可获取到服务提供者的信息,比如 ip、端口、服务协议等。通过这些信息,服务消费者就可通过 Netty 等客户端进行远程调用。
  • 一个服务集群中,provider的数量是会动态变更的,Directory从注册中心获取provider的配置信息后,会为每条配置生成对应的Invoker对象,因此Directory 可以看成是一组Invoker 的集合,它会随着注册中心的变化而动态调整。

Dubbo Cluster的作用是什么?

  • 在Dubbo体系中,集群模块是服务提供者和服务消费者的中间层,为服务消费者屏蔽了服务提供者的情况,这样服务消费者就可以专心处理远程调用相关事宜。比如发请求,接受服务提供者返回的数据等;
  • 集群 Cluster 用途是将多个服务提供者合并为一个 Cluster Invoker,并将这个 Invoker 暴露给服务消费者。这样一来,服务消费者只需通过这个 Invoker 进行远程调用即可,至于具体调用哪个服务提供者,以及调用失败后如何处理等问题,现在都交给集群模块去处理。

Dubbo Cluster的工作流程是怎样的?

  • 第一个阶段:服务消费者初始化期间,集群 Cluster 实现类为服务消费者创建 Cluster Invoker 实例;
  • 第二个阶段:
    • 服务消费者进行远程调用时,Cluster Invoker 首先会调用 Directory 的 list 方法列举 Invoker 列表;
    • 然后调用 Router 的 route 方法进行路由,过滤掉不符合路由规则的 Invoker(例如黑名单过滤);
    • 当Cluster Invoker 拿到 Directory 返回的 Invoker 列表后,它会通过 LoadBalance 从 Invoker 列表中选择一个 Invoker,通过这个Invoker实例进行远程调用。

Dubbo有哪些集群容错策略?

名称 简介
Failover 失败自动切换:当出现请求失败时,会重试其它服务器。可以通过retries设置重试次数,默认为2次。该方式是dubbo默认的容错机制,适用于读操作或幂等的写操作。
Failfast 快速失败:当请求失败后,快速返回异常结果,不做任何重试。适用于非幂等接口。
Failsafe 失败安全:当请求出现异常时,直接忽略异常。适用于佛系调用场景,即不关心调用是否成功,也不想影响外层的调用,例如不重要的日志同步等。
Failback 失败自动恢复:请求失败后,会自动记录在失败队列中,并由一个定时线程池定时重试。适用于一些异步请求或最终一致性的请求。
Forking 并行调用:同时调用多个相同的服务,只要有一个返回,则立即返回结果,可通过forks设置并行数。适用于某些对实时性要求极高的调用上,但也会浪费更多的资源。
Broadcast 广播调用:广播调用所有可用的服务,任意一个节点报错则报错。适用于服务测试。
Available 最简单的调用:请求不会做负载均衡,遍历所有服务列表,找到第一个可用的节点,直接请求并返回,如果没有可用节点则抛出异常。

Dubbo有哪些负载均衡策略?

算法名称 说明
Random LoadBalance 随机可以按权重设置随机概率,调用量越大分布月均匀
RoundRobin LoadBalance 轮询可以根据权重设置轮询比例。
LeastActive LoadBalance 最少活跃调用数根据活跃度进行分配调用,使慢的提供者收到更少的请求,如果活跃数相同则随机调用,活跃数是指调用前后的计数差。
ConsistentHash LoadBalance 一致性Hash相同参数的请求总是发到同一提供者,当某台提供者挂掉时,基于虚拟节点,相应的请求会平摊到其它提供者,不会引起剧烈变动。

限流、熔断、降级

Dubbo是如何实现限流的?

  • 通过Dubbo Service注解的executes属性配置最大并行数;
  • 限流的具体逻辑由ExecuteLimitFilter实现,本质是基于信号量控制并发数;

Dubbo中如何实现熔断?

  • Dubbo没有提供自动熔断策略;

Dubbo是否支持降级?

  • 可以通过Reference注解中的mock属性返回默认值。

性能调优

如何根据参数对Dubbo进行调优?

  • Schema 配置参考手册 | Apache Dubbo

Dubbo常见面试题与答案相关推荐

  1. Dubbo常见面试题及答案汇总1000道(春招+秋招+社招)

    Dubbo面试题以及答案整理[最新版]Dubbo高级面试题大全(2021版),发现网上很多Dubbo面试题都没有答案,所以花了很长时间搜集,本套Dubbo面试题大全,汇总了大量经典的Dubbo程序员面 ...

  2. Spring常见面试题及答案汇总1000道(春招+秋招+社招)

    Spring面试题以及答案整理[最新版]Spring高级面试题大全(2021版),发现网上很多Spring面试题都没有答案,所以花了很长时间搜集,本套Spring面试题大全,汇总了大量经典的Sprin ...

  3. 「高级java工程师」常见面试题及其答案(持续更新)

    「java工程师」常见面试题及其答案请见: 「java工程师」常见面试题及其答案(持续更新)_好人老李的博客-CSDN博客 目录 java基础 常用的 jvm 调优方法? OOM的常见场景及其原因.解 ...

  4. 「java工程师」常见面试题及其答案(持续更新)

    「高级java工程师」常见面试题及其答案: 「高级java工程师」常见面试题及其答案(持续更新)_好人老李的博客-CSDN博客 目录 java基础 面向对象与面向过程的区别? JRE.JDK.JVM的 ...

  5. 2021年最新Spring面试题,常见面试题及答案汇总

    Spring面试题以及答案整理[最新版]Spring高级面试题大全(2021版),发现网上很多Spring面试题都没有答案,所以花了很长时间搜集,本套Spring面试题大全,汇总了大量经典的Sprin ...

  6. Java多线程常见面试题及答案汇总1000道(春招+秋招+社招)

    Java多线程面试题以及答案整理[最新版]Java多线程高级面试题大全(2021版),发现网上很多Java多线程面试题都没有答案,所以花了很长时间搜集,本套Java多线程面试题大全,汇总了大量经典的J ...

  7. MySQL常见面试题及答案汇总1000道(春招+秋招+社招)

    MySQL面试题以及答案整理[最新版]MySQL高级面试题大全(2021版),发现网上很多MySQL面试题都没有答案,所以花了很长时间搜集,本套MySQL面试题大全,汇总了大量经典的MySQL程序员面 ...

  8. Jvm常见面试题及答案汇总1000道(春招+秋招+社招)

    Jvm面试题以及答案整理[最新版]Jvm高级面试题大全(2021版),发现网上很多Jvm面试题都没有答案,所以花了很长时间搜集,本套Jvm面试题大全,汇总了大量经典的Jvm程序员面试题以及答案,包含J ...

  9. JavaScript常见面试题和答案

    原文地址:https://www.yisu.com/zixun/117910.html 这篇文章将为大家详细讲解有关JavaScript常见面试题和答案,小编觉得挺实用的,因此分享给大家做个参考,希望 ...

最新文章

  1. 朋友圈里的一张组合逻辑图
  2. linux mysql 大页_Linux HugePages及MySQL 大页配置
  3. 深度学习的数学 (6)误差反向传播法必需的链式法则
  4. SpringBoot整合Minio 项目中使用自己文件存储服务器
  5. C语言(CED)对于一个2行N列的走道。现在用1*2,2*2的砖去铺满。问有多少种不同的方式(递归求解)
  6. C++函数模板5分钟入门
  7. python用turtle画菱形_使用 Python Turtle 设计简单而又美丽的图形
  8. Hyper-V 2016 系列教程28 Hyper-v平台USB 外设解决方案介绍
  9. Xml读取和写入以及新建
  10. stm32mp1 Cortex M4开发篇6:TIM定时器中断
  11. win10无法安装网卡驱动
  12. 小程序Vant组件库的使用
  13. 带状线超宽带电桥设计
  14. 【20保研】复旦大学2019年大数据学院全国优秀大学生夏令营活动方案
  15. 数字图像处理实验八图像的傅里叶变换
  16. 人工智能“算法”与“数据”的产权保护
  17. Silverlight游戏设计(Game Design):(十五)如果还有梦(完)
  18. B2C电商支付中心产品架构详解
  19. iOS开发最新最全微信第三方登录接入流程
  20. 软件测试面试拿offer拿到手软,这份简历你值得一看

热门文章

  1. php eot eod_EOD的完整形式是什么?
  2. Java FilePermission getActions()方法与示例
  3. c#二维数据最大最小值_C#| 打印类型,各种数据类型的最大值和最小值
  4. c语言memcmp和java的_C语言memcmp()函数:比较m字节长的两个字符串s1和s2
  5. 怎么查看我的php版本,怎样查看php版本
  6. mysql 线性表_数据结构之线性表
  7. MATLAB学习——常用语句
  8. java方法重载和重载方法_我们可以在Java中重载main()方法吗?
  9. 多线程循环输出abcc++_C ++循环| 查找输出程序| 套装2
  10. 从JVM入手,聊聊Java的学习和复习!