Dubbo常问面试题及答案

1、Dubbo是什么?

Dubbo是阿里巴巴开源的基于 Java 的高性能、轻量级的 RPC 分布式服务框架,可以和Spring无缝集成,并且提供了三大核心功能:面向接口的远程方法调用、智能容错和负载均衡、以及服务的自动注册和发现。

2、为什么要用Dubbo?

3、Dubbo有哪些角色?

组件角色

说明

Provider

暴露服务的服务提供方

Consumer

调用远程服务的服务消费方

Registry

服务注册与发现的注册中心

Monitor

统计服务的调用次调和调用时间的监控中心

Container

服务运行容器

4、Dubbo的各个角色的工作流程

服务容器 Container 负责启动,加载,运行服务提供者。

服务提供者 Provider 在启动时,向注册中心注册自己提供的服务。

服务消费者 Consumer 在启动时,向注册中心订阅自己所需的服务。

注册中心 Registry 返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。

服务消费者 Consumer,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。

服务消费者 Consumer 和提供者 Provider,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心 Monitor。

5、Dubbo和Spring cloud 有什么不同?

通信方式不同

Dubbo 使用的是 RPC 通信,而 Spring Cloud 使用的是 HTTP RESTFul 方式。

组成部分不同

6、Dubbo有哪几种集群容错方案,默认是哪种?

Failover Cluster(默认)

失败自动切换,当出现失败,重试其它服务器。(缺省)通常用于读操作,但重试会带来更长延迟。 可通过retries="2"来设置重试次数(不含第一次)。

或:

cluster="failover"可以不用写,因为默认就是failover

Failfast Cluster

快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。

或:

cluster="failfast"和 把cluster="failover"、retries="0"是一样的效果,retries="0"就是不重试

Failsafe Cluster

失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。

或:

Failback Cluster

失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。

或:

Forking Cluster

并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过forks="2"来设置最大并行数。

或:

forks="2"/>

Broadcast Cluster

广播调用所有提供者,逐个调用,任意一台报错则报错 [2]。通常用于通知所有提供者更新缓存或日志等本地资源信息。

7、Dubbo有哪几种负载均衡策略,默认是哪种?


8、当一个服务接口有多种实现时怎么做?

当一个接口有多种实现时,可以用 group 属性来分组,服务提供方和消费方都指定同一个 group 即可。

9、服务上线怎么兼容旧版本?

可以用版本号(version)过渡,多个不同版本的服务注册到注册中心,版本号不同的服务相互间不引用。这个和服务分组的概念有一点类似。

10 、Dubbo 支持服务降级吗?

以通过dubbo:reference 中设置 mock=“return null”。mock 的值也可以修改为 true,然后再跟接口同一个路径下实现一个 Mock 类,命名规则是 “接口名称+Mock” 后缀。然后在 Mock 类里实现自己的降级逻辑

11、Dubbo 如何优雅停机?

Dubbo 是通过 JDK 的 ShutdownHook 来完成优雅停机的,所以如果使用 kill -9 PID 等强制关闭指令,是不会执行优雅停机的,只有通过 kill PID 时,才会执行。

12、Dubbo 和 Dubbox 之间的区别?

Dubbox 是继 Dubbo 停止维护后,当当网基于 Dubbo 做的一个扩展项目,如加了服务可 Restful 调用,更新了开源组件等。

13、Dubbo 可以对结果进行缓存吗?

为了提高数据访问的速度。Dubbo提供了声明式缓存,以减少用户加缓存的工作量

其实比普通的配置文件就多了一个标签 cache=“true”

14、服务上线怎么兼容旧版本?

可以用版本号(version)过渡,多个不同版本的服务注册到注册中心,版本号不同的服务相互间不引用。这个和服务分组的概念有一点类似。

15、Dubbo必须依赖的包有哪些?

Dubbo 必须依赖 JDK,其他为可选。

16、Dubbo telnet 命令能做什么?

dubbo服务发布之后,我们可以利用telnet命令进行调试、管理。 Dubbo2.0.5以上版本服务提供端口支持telnet命令

连接服务 telnet localhost 20880 //键入回车进入Dubbo命令模式。

查看服务列表

dubbo>ls

com.test.TestService

dubbo>ls com.test.TestService

create

delete

query

ls (list services and methods)

ls : 显示服务列表。

ls -l : 显示服务详细信息列表。

ls XxxService:显示服务的方法列表。

ls -l XxxService:显示服务的方法详细信息列表。

17、Dubbo 支持分布式事务吗?

目前暂时不支持,可与通过 tcc-transaction框架实现

介绍:tcc-transaction是开源的TCC补偿性分布式事务框架

Git地址:https://github.com/changmingxie/tcc-transaction

TCC-Transaction 通过 Dubbo 隐式传参的功能,避免自己对业务代码的入侵。

Dubbo 的整体架构设计有哪些分层?

接口服务层(Service):该层与业务逻辑相关,根据 provider 和 consumer 的业务设计对应的接口和实现

配置层(Config):对外配置接口,以 ServiceConfig 和 ReferenceConfig 为中心

服务代理层(Proxy):服务接口透明代理,生成服务的客户端 Stub 和 服务端的 Skeleton,以 ServiceProxy 为中心,扩展接口为 ProxyFactory

服务注册层(Registry):封装服务地址的注册和发现,以服务 URL 为中心,扩展接口为 RegistryFactory、Registry、RegistryService

路由层(Cluster):封装多个提供者的路由和负载均衡,并桥接注册中心,以Invoker 为中心,扩展接口为 Cluster、Directory、Router和LoadBlancce

监控层(Monitor):RPC调用次数和调用时间监控,以 Statistics 为中心,扩展接口为 MonitorFactory、Monitor和MonitorService

远程调用层(Protocal):封装 RPC 调用,以 Invocation 和 Result 为中心,扩展接口为 Protocal、Invoker和Exporter

信息交换层(Exchange):封装请求响应模式,同步转异步。以 Request 和 Response 为中心,扩展接口为 Exchanger、ExchangeChannel、ExchangeClient和ExchangeServer

网络传输层(Transport):抽象 mina 和 netty 为统一接口,以 Message 为中心,扩展接口为Channel、Transporter、Client、Server和Codec

数据序列化层(Serialize):可复用的一些工具,扩展接口为Serialization、 ObjectInput、ObjectOutput和ThreadPool

默认使用的是什么通信框架,还有别的选择吗?

默认也推荐使用netty框架,还有mina。

服务调用是阻塞的吗?

默认是阻塞的,可以异步调用,没有返回值的可以这么做。

Dubbo 是基于 NIO 的非阻塞实现并行调用,客户端不需要启动多线程即可完成并行调用多个远程服务,相对多线程开销较小,异步调用会返回一个 Future 对象。

一般使用什么注册中心?还有别的选择吗?

推荐使用 Zookeeper 作为注册中心,还有 Redis、Multicast、Simple 注册中心,但不推荐。

默认使用什么序列化框架,你知道的还有哪些?

推荐使用Hessian序列化,还有Duddo、FastJson、Java自带序列化。

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

服务失效踢出基于zookeeper的临时节点原理。

如何解决服务调用链过长的问题?

可以结合zipkin实现分布式服务追踪。

Dubbo 都有哪些协议?推荐使用哪种?其它协议的使用场景是什么?

dubbo://(推荐)

rmi://

hessian://

http://

webservice://

thrift://

memcached://

redis://

rest://

Dubbo的完整调用链路

17、线程模型

需要通过不同的派发策略和不同的线程池配置的组合来应对不同的场景:

Dispatcher

all 所有消息都派发到线程池,包括请求,响应,连接事件,断开事件,心跳等。

direct 所有消息都不派发到线程池,全部在 IO 线程上直接执行。

message 只有请求响应消息派发到线程池,其它连接断开事件,心跳等消息,直接在 IO 线程上执行。

execution 只请求消息派发到线程池,不含响应,响应和其它连接断开事件,心跳等消息,直接在 IO 线程上执行。

connection 在 IO 线程上,将连接断开事件放入队列,有序逐个执行,其它消息派发到线程池。

ThreadPool

fixed 固定大小线程池,启动时建立线程,不关闭,一直持有。(缺省)

cached 缓存线程池,空闲一分钟自动删除,需要时重建。

limited 可伸缩线程池,但池中的线程数只会增长不会收缩。只增长不收缩的目的是为了避免收缩时突然来了大流量引起的性能问题。

eager 优先创建Worker线程池。在任务数量大于corePoolSize但是小

maximumPoolSize时,优先创建Worker来处理任务。当任务数量大

maximumPoolSize时,将任务放入阻塞队列中。阻塞队列充满时抛

RejectedExecutionException。(相比于cached:cached在任务数量超过maximumPoolSize时直接抛出异常而不是将任务放入阻塞队列)