一文梳理Dubbo常见面试问题

随着分布式的发展,也演变出一些很出色的分布式架构,如Spring Cloud、Dubbo等;今天带着大家一起来看看Dubbo有哪些常见的问题。

在了解一些定义之前,大家可以实操一下,去真实的感受一下Dubbo的开发流程,这些在往下看这些问题时可能感悟更深一些。
大家可以先通过这篇文章去跟着简单的实操一下:《springBoot集成dubbo》

相关文章推荐:

下面我们回到正题

1.Dubbo是什么?能干嘛?RPC又是什么?

Dubbo是一个基于分布式的远程调用框架,通过Dubbo,开发者能像调用本地方法一样调用部署在远端机器上的方法。
而RPC是Remote Procedure Call的简写,翻译成中文是远程过程调用,通过RPC,程序员能在不需要了解网络底层通讯细节的基础上调用远端服务。

关于RPC的调用方式大家可以参考下图,而Dubbo是以RPC的方式来调用远端服务。
在这里插入图片描述

而Dubbo的主要功能包括远程通讯,以集群的方式对外提供服务和服务治理。

远程通讯是指,能通过dubbo-remoting模块,提供多种基于长连接NIO框架的通讯服务。

以集群方式对外提供服务是指,提供服务的方法不仅透明,而且服务方法能以分布式的方式部署,能以负载均衡的方式提供服务,当然在提供服务的过程中还支持多协议、失败容错和动态配置等功能。

服务治理,这和微服务里的Eureka和Nacos组件很相似,能提供基于注册中心的目录服务,从而能服务提供方能自动注册服务,而服务调用方能动态查找服务。这样做的好处是,能使服务提供方以平滑的方式扩容、迁移服务或减少服务机器。

2.结合流程图,说下Dubbo的调用过程?

调用过程如下图所示:
在这里插入图片描述

我简单的解释一下上面的调用过程:

1.Proxy创建一个Invoker对象,通过Invoker开始整个流程,随后再通过Cluster组件进行以负载均衡的方式调用,在这过程中,如果失败可按之前配置的策略进行重试。

2.调用Directory模块,从底层配置里获取提供远程服务的Invoker列表,这些列表会在服务提供者模块启动或关机时自动更新。

3 如果Dubbo使用者配置了路由规则,根据指定路由规则取到Invoker列表,如果没有配置,则用默认的LoadBalance方法做负载均衡,总之这里需要找到一个可以供调用的Invoker对象。

4.调用的请求会经过“过滤器链“,其中每个过滤器会做处理上下文、限流或统计计数等动作,之后会用Client进行数据传输。

5.用Codec模块构造私有化协议,并同时进行序列化。而服务端收到该Request请求后,会把它分配到Dubbo组件里的ThreadPool模块中进行处理。

6.ThreadPool模块之后,会用Server来处理这些Request,当然之后会根据请求查找对应的Exporter,并经过服务提供者端的过滤器链。

7.最后在服务端,找到对应的接口,调用该接口并返回请求。

3.Dubbo 支持哪些协议?每种协议的应用场景及其优缺点?

1.dubbo协议,这是一种单一的长连接和 NIO 异步通讯协议,适合高并发小数据量的调用,也适用于消费者数量远大于提供者的场景,这种协议是最常用的,其中传输协议用到了TCP,采用异步通讯和Hessian 序列化的方式。

2.rmi协议,其中采用 JDK里的rmi 协议实现,传输参数传递时,需要传递的对象实现Serializable 接口,通讯时使用阻塞式短连接,适用于消费者和提供者个数差不多的场景,也可传输文件。

3.webservice协议,这是基于 比较老的WebService 远程调用协议,提供和原生 WebService 的操作接口。适用于多个短连接的场景,是用HTTP 传输的同步方式传输数据,适用于系统集成和跨语言调用的场景。

4.http协议是基于Http 表单提交的远程调用协议,比较适用于应用程序和浏览器 JS 之间的调用。

5.hessian协议是基于 HTTP 通讯,采用 Servlet 暴露服务,使用场景是,传入参数较大,提供者大于消费者,提供者压力较大等场景,通过该协议可文件。

6.memcache协议,这是基于memcached缓存实现的 RPC 协议。

7.redis协议,这是基于基于redis缓存实现的 RPC 协议。

总体来说,目前大多数Dubbo使用场景,都会用Dubbo协议,毕竟大多数使用场景是高并发场景,而且不大会传文件,如果真要传,那还不如用FTP等协议,就别用dubbo组件来传。

4.Dubbo组件中用到的设计模式?

4.1 责任链模式

Dubbo的调用链是用责任链模式串连起来的。比如Filter链就是职责链模式,通过这种模式,能通过同一条链路上的多个Filter实现监控、写日志、和安全等方面的需求功能。

4.2 观察者模式

比较典型的例子是RegistryService。消费者在初始化调用对象时会回调subscribe方法,从而注册一个观察者,如果观察者对应的的服务地址或端口列表有变更,会通过NotifyListener通知消费者,这样就达到了动态服务治理的效果。

4.3 装饰器模式

Dubbo还用到了修饰器模式,比如ProtocolFilterWrapper类是对Protocol类的修饰。

4.4 工厂模式

比如CacheFactory类的的实现方式是用到了工厂模式。CacheFactory接口定义getCache方法,然后再定义一个AbstractCacheFactory抽象类实现CacheFactory,并将实际创建cache对象的createCache方法以抽象方法的形式提取。这样cache对象的创建工作就会通过对应的子类去完成。

4.5 适配器模式

为了能让用户自己选定日志组件,Dubbo 定义了Logger 接口,并为常见的log4j和slf4j等日志组件提供了适配器,并在此基础上用工厂模式提供一个 LoggerFactory。这样用户就能在Dubbo里定义Logger,而不用关心实际的日志组件类型。

4.6 代理模式

这是Dubbo的表现形式,比如Dubbo的消费者在使用Proxy类创建远程服务的本地代理时,在本地代理中需要实现和远程服务一样的接口方法,这样能屏蔽针对远程方法调用的网络通信细节,使得用户能像调用本地方法那样调用远程方法。

5.如何在Dubbo的provider里提供了同一方法的版本的服务?

有两种方式:

  • xml配置
<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"/>
  • 基于注解
    1.provider端需要给服务的接口实现类
    在这里插入图片描述

    2.consumer端也需要加上version
    在这里插入图片描述

当你上线的时候,只需要同时修改provider,consumer端的版本号,这样在部署的时候,就会有两个不同的版本同一时刻在提供服务,这样服务不会出现大量报错的情况

6.通过流程图,说明下Dubbo的服务暴露流程?

大致的流程如下所示。
在这里插入图片描述

1.通过ServiceConfig对象解析标签,并创建dubbo的标签解析器对象来解析dubbo标签,随后通过触发ContextRefreshEvent事件的回调方法开始暴露服务的动作。

2.通过调用proxyFactory对象的getInvoker方法,并用javassist或DdkProxyFactory来进行动态代理,把服务暴露接口封装成invoker对象,在该对象里包含需要执行的方法名、参数和对应的URL地址。

3.通过DubboProtocol的实现类,把包装后的invoker转换成exporter对象。随后启动服务器端的server来监听端口,等待服务调用的到来。

4.通过RegistryProtocol对象,保存URL地址和invoker之间的映射关系,同时把这层映射关系注册到服务中心,比如Zookeeper里。

7.Dubbo的服务引用的流程

1.Dubbo客户端根据config文件里的信息从注册中心里订阅服务,并缓存到本地,后续的服务相关信息的会动态更新到本地。

2.DubboProtocol根据provider的地址和接口连接到服务端server,开启客户端client,再创建invoker。

3.用invoker为服务接口生成代理对象,这个代理对象是用来远程调用。

相关流程如下图所示。
在这里插入图片描述

8.Dubbo的常用注册中心

Zookeeper、Redis和Memcache等等都可以作为Dubbo的注册中心,不过目前用的最多的是Zookeeper。

9.Dubbo集群容错方式

1.Failover Cluster,这是失败自动切换模式,也是dubbo集群默认容错方案,即当调用失败时自动切换到其他可用的节点,其中的重试次数和间隔时间用户可配置。

2.Failback Cluster,这是失败自动恢复模式,在调用失败时通过日志记录调用信息,然后向消费者返回空结果,并通过定时任务,按一定频率(可配置,默认是5秒) 对失败的调用进行重试。

3.Failfast Cluster,即快速失败模式,只调用一次,失败后立刻抛出异常。

4.Failsafe Cluster,即失败安全模式,调用出现异常时,记录日志但不抛出异常,同时向消费者返回空结果。

5.Forking Cluster,即并行调用多个服务提供者,具体做法是通过线程池创建多个线程,并发调用多个provider,结果存到阻塞队列,只要有一个provider成功返回了结果,就会立刻返回结果,但这种容错方式是以牺牲性能的方式来确保成功率。

6.Broadcast Cluster,即广播模式,逐个调用每个provider,如果其中一台服务器报异常,就在循环调用后,抛出该异常。

10.Dubbo的分层

分层图如下所示。
在这里插入图片描述

business业务逻辑层(Biz层)是由程序员定义的接口和配置信息构成。需要说明的是,Service和Config这两层也可认为是API层,因为主要是给程序员使用。

RPC层封装了整个RPC的调用过程、负载均衡、集群容错和代理方式等底层信息。

Remoting层则封装了网络传输协议和数据转换的实现细节。

后面的是SPI层,主要提供给扩展者使用,程序员可以通过重写其中的代码和配置来进行Dubbo的二次开发。

11.Dubbo原理

在这里插入图片描述

Dubbo角色:

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

调用过程:

0:服务器容器负责启动、加载、运行服务提供者

1:服务提供者在启动后就可以向注册中心暴露服务

2:服务消费者在启动后就可以向注册中心订阅想要的服务

3:注册中心向服务消费者返回服务调用列表

4:服务消费者基于软负载均衡算法调用服务提供者的服务,这个服务提供者有可能是一个服务提供者列表,调用那个服务提供者就是根据负载均衡来调用了

5:服务提供者和服务消费者定时将保存在内存中的服务调用次数和服务调用时间推送给监控中心

猜你喜欢

转载自blog.csdn.net/zhiyikeji/article/details/125733658