Dubbo面试指南

351 阅读6分钟

什么是DUBBO?

Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,以及 SOA 服务治理方案。

聊一下DUBBO是如何进行服务的注册与发现的?

  1. 服务提供者启动的时候,会向注册中心提供自己提供的服务。
  2. 服务消费者在启动的时候,向注册中心订阅自己所需的服务。
  3. 注册中心会返回服务提供者地址列表给消费者,如果有变更,注册中心会基于长连接推送变更数据给消费者。
  4. 服务消费者Consumer,从提供者地址列表基于负载均衡算法,选取一台进行调用,如果调用失败,再换一台。

Dubbo主要分了几层?

  1. 接口服务层:包含了提供者和消费者对应的接口和实现。
  2. 配置层: 对外配置接口,通过ServiceConfig和ReferenceConfig来实现。
  3. 服务代理层:服务接口的透明代理,dubbo实际调用都是通过代理来实现的。
  4. 服务注册层:封装服务地址的注册和发现,以服务URL为中心。
  5. 路由层: 封装多个提供者的路由和负载均衡。
  6. 监控层:监控生产者和消费者的调用次数以及时间等监控。
  7. 远程调用层:封装RPC调用
  8. 信息交换层:封装请求响应,同步转异步等。
  9. 网络传输层:使用netty或者mina等网络传输框架 10.序列化层: 数据序列化。

服务的注册流程?

  1. 通过 ServiceConfig 解析标签,创建 dubbo 标签解析器来解析 dubbo 的标签。容器创建完成之后,触发 ContextRefreshEvent 事件回调开始暴露服务;
  2. 通过 ProxyFactory.getInvoker 方法,并利用 Javassist 或 JdkProxyFactory 来进行动态代理,将服务暴露接口封装成 Invoker 对象,里面包含了需要执行的方法的对象信息和具体的 URL 地址;
  3. 再通过 DubboProtocol 的实现把包装后的 Invoker 转换成 Exporter;
  4. 然后启动服务器 server,监听客户端的请求。
  5. 最后 RegistryProtocol 保存 URL 地址和 Invoker 映射关系,同时注册到服务中心。

服务的引用流程?

  1. 首先,客户端根据 config 文件信息从注册中心订阅服务。首次会全量缓存到本地,后续的更新会监听动态更新到本地。
  2. 接着,DubboProtocol 根据 provider 的地址和接口信息连接到服务端 server。开启客户端 client,然后创建invoker。
  3. 然后,通过 invoker 为服务接口生成代理对象,这个代理对象用于远程调用 provider,至此完成了服务引用。

服务总体调用流程?

  1. Proxy 持有一个 Invoker 对象,使用 Invoker 调用;
  2. 之后通过 Cluster 进行负载容错,失败重试;
  3. 调用 Directory 获取远程服务的 Invoker 列表;
  4. 负载均衡
    1. 用户配置了路由规则,则根据路由规则过滤获取到的 Invoker 列表;
    2. 用户没有配置路由规则,或配置路由后还有很多节点时,则使用 LoadBalance 方法做负载均衡,选用一个可以调用的 Invoker。
  5. 经过一个一个过滤器链,通常是处理上下文、限流、计数等;
  6. 会使用 Client 做数据传输;
  7. 私有化协议的构造(Codec);
  8. 进行序列化;
  9. 服务端收到这个 Request 请求,将其分配到 ThreadPool 中处理;
  10. Server 来处理这些 Request;
  11. 根据请求查找对应的 Exporter;
  12. 之后经过一个服务提供者端的过滤器链;
  13. 然后找到接口实现并真正的调用,将请求结果返回。

Dubbo多版本如何解决?

可以直接通过 Dubbo 配置中的 version 版本来控制多个版本即可。比如:

<dubbo:service interface="com.xxxx.rent.service.IDemoService" ref="iDemoServiceFirst" version="1.0.0"/>
<dubbo:service interface="com.xxxx.rent.service.IDemoService" ref="iDemoServiceSecond" version="1.0.1"/>

老版本 version=1.0.0,新版本 version=1.0.1。

聊聊Dubbo SPI机制?

  1. SPI(Service Provider Interface)是一种服务发现机制。其实就是将结构的实现类写入配置当中,在服务加载的时候读取配置文件,加载实现类。这样就可以在运行的时候,动态帮助接口替换实现类。
  2. Dubbo 的 SPI 其实是对 Java 的 SPI 进行了一种增强,可以按需加载实现类之外,增加了 IOC 和 AOP 的特性,还有自适应扩展机制。
  3. SPI 在 dubbo 应用很多,包括协议扩展、集群扩展、路由扩展、序列化扩展等。
  4. Dubbo 对于文件目录的配置分为了三类:
    1. META-INF/services/ 目录:该目录下的 SPI 配置文件是为了用来兼容 Java SPI;
    2. META-INF/dubbo/ 目录:该目录存放用户自定义的 SPI 配置文件:key=com.xxx.xxx;
    3. META-INF/dubbo/internal/ 目录:该目录存放 Dubbo 内部使用的 SPI 配置文件。

DubboSPI和JDKSPI的区别?

  1. JavaSPI:在查找扩展实现类的时候遍历SPI的配置文件,并将实现类全部实例化。
  2. DubboSPI:
    1. 对Dubbo进行扩展不需要改动Dubbo源代码
    2. 支持延迟加载
    3. 增加了对扩展点IOC和AOP的支持。
    4. Dubbo的扩展机制很好的支持第三方IOC容器,默认支持Spring Bean。

Dubbo有哪些负载均衡策略?

  1. 加权随机 1.比如我们有三台服务器 [A, B, C],给他们设置权重为 [4, 5, 6],然后将这三个数平铺在水平线上,和为 15。然后在 15 以内生成一个随机数,0~4 是服务器 A,4~9 是服务器 B,9~15 是服务器 C。
  2. 最小活跃数
    1. 每个服务提供者对应一个活跃数 active。初始情况下,所有服务提供者活跃数均为 0。每收到一个请求,活跃数加 1,完成请求后则将活跃数减 1。
    2. 在服务运行一段时间后,性能好的服务提供者处理请求的速度更快,因此活跃数下降的也越快,此时这样的服务提供者能够优先获取到新的服务请求。
  3. 一致性Hash

集群容错方式有哪些?

  1. Failover Cluster 失败自动切换:dubbo 的默认容错方案,当调用失败时自动切换到其他可用的节点。具体的重试次数和间隔时间可用通过引用服务的时候配置。默认重试次数为 1 即只调用一次;
  2. Failback Cluster 失败自动恢复:在调用失败,记录日志和调用信息,然后返回空结果给 consumer,并且通过定时任务每隔 5 秒对失败的调用进行重试;
  3. Failfast Cluster 快速失败:只会调用一次,失败后立刻抛出异常;
  4. Failsafe Cluster 失败安全:调用出现异常,记录日志不抛出,返回空结果;
  5. Forking Cluster 并行调用多个服务提供者:通过线程池创建多个线程,并发调用多个 provider,结果保存到阻塞队列。只要有一个 provider 成功返回了结果,就会立刻返回结果;
  6. Broadcast Cluster 广播模式:逐个调用每个 provider。如果其中一台报错,在循环调用结束后,抛出异常。

服务提供者能实现失效踢出是什么原理?

Zookeeper 中的节点是有生命周期的,具体的生命周期取决于节点的类型。节点主要分为持久(Persistent)节点和临时(Ephemeral)节点 。

ps:文章参考:mp.weixin.qq.com/s/S2ckynSFD…