Dubbo 面试题及答案

文章目录

1.Dubbo是什么?

Apache Dubbo是一款高性能、轻量级的开源Java 服务框架。

2.为什么要用Dubbo?

因为是阿里开源项目,国内很多互联网公司都在用,已经经过很多线上考验。内部使用了Netty、Zookeeper,保证了高性能高可用性。

随着服务化的进一步发展,服务越来越多,服务之间的调用和依赖关系也越来越复杂,诞生了面向服务的架构体系(SOA),

也因此衍生出了一系列相应的技术,如对服务提供、服务调用、连接处理、通信协议、序列化方式、服务发现、服务路由、日志输出等行为进行封装的服务框架。

就这样为分布式系统的服务治理框架就出现了,Dubbo也就这样产生了。

使用Dubbo可以将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,可用于提高业务复用灵活扩展,使前端应用能更快速的响应多变的市场需求。

下面这张图可以很清楚的诠释,最重要的一点是,分布式架构可以承受更大规模的并发流量。
在这里插入图片描述

下面是Dubbo的服务治理图
在这里插入图片描述

3.Dubbo 和 Dubbox 有什么区别?

  • Dubbox和Dubbo都是流行的服务治理框架。
  • Dubbox是继Dubbo停止维护后,当当网基于Dubbo做的一个扩展项目,主要扩展的功能是支持REST风格远程调用(HTTP + JSON/XML)和支持基于Kryo和FST的Java高效序列化实现。

4.Dubbo 停止维护了吗?

2014 年开始停止维护过几年,17 年开始重新维护,并进入了 Apache 项目。

5.你读过 Dubbo 的源码吗?

Dubbo的源码地址: https://github.com/apache/Dubbo

下图中Dubbo的版本是2.7.4
各种注册中心的实现
在这里插入图片描述
各种协议的实现
在这里插入图片描述
消费者各种容错机制
在这里插入图片描述
消费端各种负载均衡机制
在这里插入图片描述
dubbo源码中重要包结构的阐释:

  • dubbo-common 公共逻辑模块,包括Util类和通用模型。
  • dubbo-remoting 远程通讯模块,相当于Dubbo协议的实现,如果RPC用RMI协议则不需要使用此包。
  • dubbo-rpc 远程调用模块,抽象各种协议,以及动态代理,只包含一对一的调用,不关心集群的管理。
  • dubbo-cluster 集群模块,将多个服务提供方伪装为一个提供方,包括:负载均衡、容错、路由等,集群的地址列表可以是静态配置的,也可以是由注册中心下发。
  • dubbo-registry 注册中心模块,基于注册中心下发地址的集群方式,以及对各种注册中心的抽象。
  • dubbo-monitor 监控模块,统计服务调用次数,调用时间的,调用链跟踪的服务。
  • dubbo-config 配置模块,是Dubbo对外的API,用户通过Config使用Dubbo,隐藏Dubbo所有细节。
  • dubbo-container 容器模块,是一个Standalone的容器,以简单的Main加载Spring启动,因为服务通常不需要Tomcat/JBoss等Web容器的特性,没必要用Web容器去加载服务。

6.在使用过程中都遇到了些什么问题?

Dubbo 的设计目的是为了满足高并发小数据量的 rpc 调用,在大数据量下的性能表现并不好,建议使用 rmi 或 http 协议。

扫描二维码关注公众号,回复: 13650576 查看本文章

举例两个常见的遇到的问题,还有其他的很多,等等。
1.出现RpcException: No provider available for remote service异常怎么办?
表示没有可用的服务提供者,
1). 检查连接的注册中心是否正确
2). 到注册中心查看相应的服务提供者是否存在
3). 检查服务提供者是否正常运行

2.Data length too large
这个异常的详细堆栈信息如下所示:

org.apache.dubbo.remoting.transport.ExceedPayloadLimitException:
Data length too large: 10356612, max payload: 8388608,
channel: NettyChannel [channel=[id: 0xd36132c0, L:/192.168.1.6:55078 - R:/192.168.1.6:20880]]

日志中提到max payload为8388608,等价于8 * 1024 * 1024,即8k。所以这个问题的原因非常清晰了,就是请求或者响应的报文体长度超过了8k。
这个问题比较简单,笔者在这里提供两个解决方案:

  1. 修改payload的值,将其调大,例如16777216,即16k,不推荐;
  2. 减少请求/响应报文长度。例如Provider提供的服务,最大批量限制为1000,比如最多只能批量查询1000个用户ID的用户信息,推荐

7.Dubbo和SpringCloud的区别?springcloud和Dubbo的对比?你觉得用 Dubbo 好还是 Spring Cloud 好?

1)通信方式不同

  • Dubbo 使用的是 RPC 通信,而 Spring Cloud 使用的是 HTTP RESTFul 方式。
  • 由于Dubbo底层是使用Netty这样的NIO框架,是基于TCP协议传输的,配合以Hession序列化完成RPC。
  • SpringCloud是基于Http协议+rest接口调用远程过程的,相对来说,Http请求会有更大的报文,占的带宽也会更多。

2)组成部分不同
在这里插入图片描述
3)社区活跃度

  • Dubbo的更新数度慢,更新频率低
  • 相比于 Dubbo,spring Cloud是一个正在持续维护的、社区更加火热的开源项目,这就可以保证使用它构建的系统持续地得到开源力量的支持。

8.Dubbo 能集成 Spring Boot 吗?

可以。https://github.com/apache/incubator-Dubbo-spring-boot-project

9.Dubbo支持的序列化协议?

Dubbo 支持 hession、Java 二进制序列化、json、SOAP 文本序列化多种序列化协议。但是 hessian 是其默认的序列化协议。

说一下 Hessian 的数据结构

Hessian 的对象序列化机制有 8 种原始类型:

  • 原始二进制数据
  • boolean
  • 64-bit date(64 位毫秒值的日期)
  • 64-bit double
  • 32-bit int
  • 64-bit long
  • null
  • UTF-8 编码的 string

另外还包括 3 种递归类型:

  • list for lists and arrays
  • map for maps and dictionaries
  • object for objects

还有一种特殊的类型:

  • ref:用来表示对共享对象的引用。

10.Dubbo支持的通信协议?Dubbo调用RPC有几种协议可以用?

  • Dubbo 协议
    • 默认就是 Dubbo 协议,单一长连接,进行的是 NIO 异步通信,基于 hessian 作为序列化协议。使用的场景是:传输数据量小(每次请求在 100kb 以内),但是并发量很高。以及消费者远大于提供者。
    • 为了要支持高并发场景,一般是服务提供者就几台机器,但是服务消费者有上百台,可能每天调用量达到上亿次!此时用长连接是最合适的,就是跟每个服务消费者维持一个长连接就可以,可能总共就 100 个连接。然后后面直接基于长连接 NIO 异步通信,可以支撑高并发请求。
  • rmi 协议
    • 采用JDK标准的rmi协议实现,传输参数和返回参数对象需要实现Serializable接口,使用java标准序列化机制,传输数据包大小混合,消费者和提供者个数差不多,可传文件,传输协议TCP。
    • Java 二进制序列化,多个短连接,适合消费者和提供者数量差不多的情况,适用于文件的传输,一般较少用。
  • hessian 协议
    • hessian 序列化协议,多个短连接,适用于提供者数量比消费者数量还多的情况,适用于文件的传输,一般较少用。
    • 集成Hessian服务,基于HTTP通讯,采用Servlet暴露服务,Dubbo内嵌Jetty作为服务器时默认实现,提供与Hession服务互操作。
  • http 协议
    • json 序列化。
    • 基于Http表单提交的远程调用协议,使用Spring的HttpInvoke实现。多个短连接,传输协议HTTP,传入参数大小混合,提供者个数多于消费者,需要给应用程序和浏览器JS调用;
  • webservice
    • SOAP 文本序列化。
    • 基于WebService的远程调用协议,集成CXF实现,提供和原生WebService的互操作。多个短连接,基于HTTP传输,同步传输,适用系统集成和跨语言调用;
  • memcache
    • 基于memcached实现的RPC协议
  • redis
    • 基于redis实现的RPC协议
  • thrift 协议
    • 当前 Dubbo 支持的 thrift 协议是对 thrift 原生协议 [2] 的扩展,在原生协议的基础上添加了一些额外的头信息,比如 service name,magic number 等。
  • RESTful
    • 基于标准的Java REST API——JAX-RS 2.0(Java API for RESTful Web Services的简写)实现的REST调用支持。

11.Dubbo支持服务多协议吗?

Dubbo允许配置多协议,在不同的服务上支持不同协议或者同一服务器上同时支持多种协议。

12.Dubbo服务器、Zookeeper服务器各有几个角色节点?

Dubbo

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

zookeeper

  • Leader(领导者):Leader 服务器是整个 ZooKeeper 集群工作机制中的核心
    • 事务请求的唯一调度和处理者,保证集群事务处理的顺序性。
    • 集群内部各服务器的调度者。
  • Follwer(跟随者):
    • 处理客户端非事务请求,转发事务请求给 Leader 服务器。
    • 参与事务请求 Proposal 的投票。
    • 参与 Leader 选举投票。
  • ObServer(观察者):
    • 接收客户端连接,将写请求转发给leader节点,但ObServer不参与投票,只填报leader的状态。
    • ObServer目的是为了扩展系统,提高读取速度。

13.Dubbo框架图?Dubbo架构图?画一画服务注册与发现的流程图?

在这里插入图片描述
具体的流程过程参考文章:Dubbo的架构设计

15.Dubbo默认使用什么注册中心,还有别的选择吗?

推荐使用 Nacos 作为注册中心,还有Zookeeper, Redis、Multicast、Simple 注册中心,但不推荐。Zookeeper是强一致性,会出现服务不可用的情况。

16.在 Provider 上可以配置的 Consumer 端的属性有哪些?

  • timeout:方法调用超时
  • retries:失败重试次数,默认重试2次
  • loadbalance:负载均衡算法,默认随机
  • actives:消费者端,最大并发调用限制

17.Dubbo启动时如果依赖的服务不可用会怎样?

Dubbo缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止Spring初始化完成,默认check=“true”,可以通过 check=“false” 关闭检查。

18.注册了多个同一样的服务,如果测试指定的某一个服务呢?

可以配置环境点对点直连,绕过注册中心,将以服务接口为单位,忽略注册中心的提供者列表。

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

基于Zookeeper的临时节点原理

20.说说 Dubbo 服务暴露的过程

  • Dubbo会在Spring实例化完bean之后,在刷新容器最后一步发布ContextRefreshEvent事件的时候,那么 Dubbo 通过DubboBootstrapApplicationListener 监听类来接收 ContextRefreshedEvent 事件。(这是 Dubbo 与 Spring 整合的切入点)
  • 当监听器接收到 ContextRefreshedEvent 事件后,Dubbo 会做以下几点事情:暴露服务、导出元数据、注册本地服务实例、初始化远程调用代理对象。导出元数据(在 Dubbo2.7.x 中元数据和配置信息是分离的这里仅仅导出的是元数据)、注册本地实例(在 JVM 导出服务)、初始化远程代理对象(其实就是创建一个调用远程的 Invoker 代理对象)。
  • 通知实现了ApplicationListener 的 ServiceBean 类进行回调 onApplicationEvent 事件方法,Dubbo会在这个方法中调用ServiceBean父类ServiceConfig的export方法,而该方法真正实现了服务的(异步或者非异步)发布。
    详细过程见下图:
    在这里插入图片描述
  1. ServiceConfig类拿到对外提供服务的实现类ref(如:HelloWorldImpl)
  2. 通过ProxyFactory类的getInvoker方法使用ref生成一个AbstractProxyInvoker实例,到这一步就完成具体服务到Invoker的转化。
  3. 接下来就是Invoker转换到Exporter的过程。Dubbo处理服务暴露的关键就在Invoker转换到Exporter的过程(如上图中的红色部分)。 Dubbo协议的Invoker转为Exporter发生在DubboProtocol类的export方法,它主要是打开socket侦听服务,并接收客户端发来的各种请求,通讯细节由Dubbo自己实现。
    @Override
    public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
    
    
        checkDestroyed();
        URL url = invoker.getUrl();

        // export service.
        String key = serviceKey(url);
        DubboExporter<T> exporter = new DubboExporter<T>(invoker, key, exporterMap);

        //export a stub service for dispatching event
        Boolean isStubSupportEvent = url.getParameter(STUB_EVENT_KEY, DEFAULT_STUB_EVENT);
        Boolean isCallbackservice = url.getParameter(IS_CALLBACK_SERVICE, false);
        if (isStubSupportEvent && !isCallbackservice) {
    
    
            String stubServiceMethods = url.getParameter(STUB_EVENT_METHODS_KEY);
            if (stubServiceMethods == null || stubServiceMethods.length() == 0) {
    
    
                if (logger.isWarnEnabled()) {
    
    
                    logger.warn(new IllegalStateException("consumer [" + url.getParameter(INTERFACE_KEY) +
                            "], has set stubproxy support event ,but no stub methods founded."));
                }

            }
        }

        openServer(url);
        optimizeSerialization(url);

        return exporter;
    }

21.Dubbo服务注册与校验的过程

在上面的我们了解了Dubbo服务暴露的过程,服务暴露完了以后,当我们需要暴露一个服务给其他应用端调用时那么应用端是怎样知道我们的服务在哪里?暴露了什么接口?通讯端口是多少?这些信息客户端是怎样获取的呢?这些都需要我们的服务提供者向我们的注册中心注册,消费端获取这些注册元信息再进行远程调用。那么服务提供者向注册中心注册元信息的过程就是服务注册。整个服务注册过程大致包括了:参数检测,URL 组装、本地服务导出,远程服务导出、注册中心服务注册。

22.服务消费者消费一个服务的详细过程

在这里插入图片描述

  1. ReferenceConfig类的init方法调用Protocol的refer方法生成Invoker实例(如上图中的红色部分),这是服务消费的关键。
  2. 把Invoker转换为客户端需要的接口(如:HelloWorld)。这里获取invoker的时候,如果是注册中心同一个服务有多个提供者,消费者会根据配置的负载均衡来选择出一个作为提供者来使用。并且也有各种容错处理机制。

以DubboProtocol为例,使用refer方法生成Invoker实例的示例代码如下:

  @Override
    public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
    
    
        checkDestroyed();
        return protocolBindingRefer(type, url);
    }

    @Override
    public <T> Invoker<T> protocolBindingRefer(Class<T> serviceType, URL url) throws RpcException {
    
    
        checkDestroyed();
        optimizeSerialization(url);

        // create rpc invoker.
        DubboInvoker<T> invoker = new DubboInvoker<T>(serviceType, url, getClients(url), invokers);
        invokers.add(invoker);

        return invoker;
    }

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

Dubbo可以使用zipkin或者Pinpoint和Apache Skywalking(Incubator)实现分布式服务追踪

24.Dubbo服务之间的调用是阻塞的吗?

默认是同步等待结果阻塞的,支持异步调用。
Dubbo是基于NIO的非阻塞实现并行调用,客户端不需要启动多线程即可完成并行调用多个远程服务,相对多线程开销较小,异步调用会返回一个Future对象。
异步调用流程图如下:
在这里插入图片描述

25.Dubbo的超时设置

  • 针对方法设置超时时间
  • 在服务方设置超时时间
  • 在调用方设置超时时间

详细的参考文章:Dubbo的超时和重试

26.Dubbo的重试机制

  • Dubbo在调用服务不成功时,默认会重试2次。加上初始一次,总共调用提供者3次
  • Dubbo的路由机制,会把超时的请求路由到其他机器上,而不是本次尝试,所以Dubbo的重试机制也能一定程度的保证服务的治理。
  • 如果不合理的配置重试次数,当失败时会进行重试多次,这样在某个时间点出现性能问题,调用方再连续重复调用,系统请求变为正常值的retries倍,系统压力会大增,容易引起服务雪崩,需要根据业务情况规划好如何进行异常处理,何时进行重试。
<dubbo:reference id="xx" interface="xx"  retries="2" timeout="3000"/>
  1. timeout=“3000” ,服务调用的超时时间,调用服务的过程中如果达到3秒就会报超时异常,超时异常后客户端会进行尝试设定的“retries”次调用。有一个需要注意的地方,timeout只有在超时异常才有效,如果是其他异常导致dubbo服务调用抛异常,会立即进入下一次尝试。
  2. retries=“2” ,即重试两次,如果失败就抛出异常。

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

  • Failover Cluster:失败自动切换,自动重试其他服务器。默认容错方案
  • Failfast Cluster:快速失败,立即报错,只发起一次调用。
  • Failsafe Cluster:失败安全,出现异常时,直接忽略。
  • Failback Cluster:失败自动恢复,记录失败请求,定时重发。
  • Forking Cluster:并行调用多个服务器,只要一个成功即返回。
  • Broadcast Cluster:广播逐个调用所有提供者,任意一个报错则报错。

28.服务读写推荐的容错策略是怎样的?

读操作建议使用Failover失败自动切换,默认重试两次其他服务器。
写操作建议使用Failfast快速失败,发一次调用失败就立即报错。

29.Dubbo有哪几种负载均衡策略,默认是哪种?Dubbo的负载均衡原理?

  • Random LoadBalance:随机,按权重设置随机概率。默认
  • RoundRobin LoadBalance:轮询,按公约后的权重设置轮询比率。
  • LeastActive LoadBalance:最少活跃调用数,相同活跃数的随机。
  • ConsistentHash LoadBalance:一致性Hash,相同参数的请求总是发到同一提供者。

具体的负载均衡原理,可以参考以下文章:Dubbo-负载均衡原理解析

30.Dubbo支持服务降级吗?

  • Dubbo 2.2.0 以上版本支持。
  • Dubbo提供了mock配置,可以很好的实现Dubbo服务降级。mock只在出现非业务异常(比如超时,网络异常等)时执行。
  • mock的配置支持两种
    • Mock Class降级处理:boolean值,默认的为false。如果配置为true,则缺省使用mock类名,即类名+Mock后缀;
    • Mock Null降级处理:配置"return null",可以很简单的忽略掉异常。

31.Dubbo如何优雅停机?

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

32.Dubbo可以对结果进行缓存吗?

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

33.了解哪些rpc框架?你还了解别的分布式框架吗?

  • Thrift:
    • thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml 这些编程语言间无缝结合的、高效的服务。
  • Dubbo:
    • 国内最早开源的 RPC 框架,仅支持 Java 语言。
    • Dubbo是一个分布式服务框架,以及SOA治理方案。其功能主要包括:高性能NIO通讯及多协议集成,服务动态寻址与路由,软负载均衡与容错,依赖分析与降级等。 Dubbo是阿里巴巴内部的SOA服务化治理方案的核心框架,Dubbo自2011年开源后,已被许多非阿里系公司使用。
  • Spring Cloud:
    • Spring Cloud由众多子项目组成,如Spring Cloud Config、Spring Cloud Netflix、Spring Cloud Consul 等,提供了搭建分布式系统及微服务常用的工具,如配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性token、全局锁、选主、分布式会话和集群状态等,满足了构建微服务所需的所有解决方案。
    • Spring Cloud基于Spring Boot, 使得开发部署极其简单。
  • gRPC:
    • 一开始由 google 开发,是一款语言中立、平台中立、开源的远程过程调用(RPC)系统。
  • Motan:
    • 微博内部使用的 RPC 框架,于 2016 年对外开源,仅支持 Java 语言。
  • Tars:
    • 腾讯内部使用的 RPC 框架,于 2017 年对外开源,仅支持 C++ 语言。

34.Dubbo的原理?Dubbo是基于什么实现的?底层是怎么实现的?

Dubb的底层通信是利用netty来实现的。

具体实现的源码,参考资料:https://zhuanlan.zhihu.com/p/97762356

35.Dubbo的线程模型

在这里插入图片描述

Dubbo线程模型包括线程模型策略和Dubbo线程池策略两个方面。

线程模型策略

Dubbo默认的底层网络通信使用的是Netty,服务提供方NettyServer使用两级线程池,其中EventLoopGroup(boss)主要用来接收客户端的链接请求,并把完成TCP三次握手的连接分发给EventLoopGroup(worker)来处理,注意把boss和worker线程组称为I/O线程,前者处理IO连接事件,后者处理IO读写事件。

Dubbo中根据请求的消息类是直接被I/O线程处理还是被业务线程池处理,Dubbo提供了下面几种线程模型:
在这里插入图片描述

  • all(AllDispatcher类):所有消息都派发到业务线程池,这些消息包括请求、响应、连接事件、断开事件等,响应消息会优先使用对于请求所使用的线程池。
  • direct(DirectDispatcher类):所有消息都不派发到业务线程池,全部在IO线程上直接执行。
  • message(MessageOnlyDispatcher类):只有请求响应消息派发到业务线程池,其他消息如连接事件、断开事件、心跳事件等,直接在I/O线程上执行。
  • execution(ExecutionDispatcher类):只把请求类消息派发到业务线程池处理,但是响应、连接事件、断开事件、心跳事件等消息直接在I/O线程上执行。
  • connection(ConnectionOrderedDispatcher类):在I/O线程上将连接事件、断开事件放入队列,有序地逐个执行,其他消息派发到业务线程池处理。

Dubbo线程池可选模型较多,下面以DirectDispatcher类进行分析:

public class DirectChannelHandler extends WrappedChannelHandler {
    
    

    public DirectChannelHandler(ChannelHandler handler, URL url) {
    
    
        super(handler, url);
    }

    @Override
    public void received(Channel channel, Object message) throws RemotingException {
    
    
        ExecutorService executor = getPreferredExecutorService(message);
        if (executor instanceof ThreadlessExecutor) {
    
    
            try {
    
    
                executor.execute(new ChannelEventRunnable(channel, handler, ChannelState.RECEIVED, message));
            } catch (Throwable t) {
    
    
                throw new ExecutionException(message, channel, getClass() + " error when process received event .", t);
            }
        } else {
    
    
            handler.received(channel, message);
        }
    }

}

DirectDispatcher类重写了received方法,注意 ThreadlessExecutor 被应用在调用 future.get() 之前,先调用 ThreadlessExecutor.wait(),wait 会使业务线程在一个阻塞队列上等待,直到队列中被加入元素。很明显,provider侧调用getPreferredExecutorService(message)返回的不是ThreadlessExecutor,所以会在当前IO线程执行执行。

其他事件,比如连接、异常、断开等,都是在WrappedChannelHandler中默认实现:执行在当前IO线程中执行的,代码如下:

    @Override
    public void connected(Channel channel) throws RemotingException {
    
    
        handler.connected(channel);
    }

    @Override
    public void disconnected(Channel channel) throws RemotingException {
    
    
        handler.disconnected(channel);
    }

    @Override
    public void sent(Channel channel, Object message) throws RemotingException {
    
    
        handler.sent(channel, message);
    }

    @Override
    public void received(Channel channel, Object message) throws RemotingException {
    
    
        handler.received(channel, message);
    }

    @Override
    public void caught(Channel channel, Throwable exception) throws RemotingException {
    
    
        handler.caught(channel, exception);
    }

Dubbo线程池策略

Dubbo处理流程,为了尽量早地释放Netty的I/O线程,某些线程模型会把请求投递到线程池进行异步处理,那么这里所谓的线程池是什么样的线程池呢?

其实这里的线程池ThreadPool也是一个扩展接口SPI,Dubbo提供了该扩展接口的一些实现,具体如下:

  • FixedThreadPool:创建一个具有固定个数线程的线程池。
  • LimitedThreadPool:创建一个线程池,这个线程池中的线程个数随着需要量动态增加,但是数量不超过配置的阈值。另外,空闲线程不会被回收,会一直存在。
  • EagerThreadPool:创建一个线程池,在这个线程池中,当所有核心线程都处于忙碌状态时,将创建新的线程来执行新任务,而不是把任务放入线程池阻塞队列。
  • CachedThreadPool:创建一个自适应线程池,当线程空闲1分钟时,线程会被回收;当有新请求到来时,会创建新线程。

知道了这些线程池之后,那么是什么时候进行SPI加载对应的线程池实现呢?具体是在Dubbo 线程模型获取对应线程池时进行SPI加载的,具体逻辑在方法 org.apache.dubbo.common.threadpool.manager.DefaultExecutorRepository#createExecutor中:

private ExecutorService createExecutor(URL url) {
    
    
        return (ExecutorService) extensionAccessor.getExtensionLoader(ThreadPool.class).getAdaptiveExtension().getExecutor(url);
    }

@SPI(value = "fixed", scope = ExtensionScope.FRAMEWORK)
public interface ThreadPool {
    
    

    /**
     * Thread pool
     *
     * @param url URL contains thread parameter
     * @return thread pool
     */
    @Adaptive({
    
    THREADPOOL_KEY})
    Executor getExecutor(URL url);

}

从代码来看,默认的线程池策略是fixed模式的线程池,其coreSize默认为200,队列大小为0,其代码如下:

/**
 * Creates a thread pool that reuses a fixed number of threads
 *
 * @see java.util.concurrent.Executors#newFixedThreadPool(int)
 */
public class FixedThreadPool implements ThreadPool {
    
    

    @Override
    public Executor getExecutor(URL url) {
    
    
        String name = url.getParameter(THREAD_NAME_KEY, (String) url.getAttribute(THREAD_NAME_KEY, DEFAULT_THREAD_NAME));
        int threads = url.getParameter(THREADS_KEY, DEFAULT_THREADS);
        int queues = url.getParameter(QUEUES_KEY, DEFAULT_QUEUES);
        return new ThreadPoolExecutor(threads, threads, 0, TimeUnit.MILLISECONDS,
                queues == 0 ? new SynchronousQueue<Runnable>() :
                        (queues < 0 ? new LinkedBlockingQueue<Runnable>()
                                : new LinkedBlockingQueue<Runnable>(queues)),
                new NamedInternalThreadFactory(name, true), new AbortPolicyWithReport(name, url));
    }

}

36.Dubbo需要 Web 容器吗?

不需要,如果硬要用 Web 容器,只会增加复杂性,也浪费资源。

37.Dubbo内置了哪几种服务容器?

Dubbo 的服务容器只是一个简单的 Main 方法,并加载一个简单的 Spring 容器,用于暴露服务。

  • Spring Container
  • Jetty Container
  • Log4j Container

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

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

39.服务上线怎么兼容旧版本?

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

40.Dubbo支持分布式事务吗?

  • 目前暂时不支持。可与通过 tcc-transaction 框架实现
  • tcc-transaction 是开源的 TCC 补偿性分布式事务框架 。
  • Git 地址:https://github.com/changmingxie/tcc-transaction
  • TCC-Transaction 通过 Dubbo 隐式传参的功能,避免自己对业务代码的入侵。

41.Dubbo telnet 命令能做什么?

dubbo 通。过 telnet 命令来进行服务治理。具体使用看这篇文章《dubbo服务调试管理实用命令》。

42.Dubbo必须依赖的包有哪些?

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

43.Dubbo的管理控制台能做什么?

管理控制台主要包含:路由规则,动态配置,服务降级,访问控制,权重调整,负载均衡,等等

44.Dubbo有哪几种配置方式?

  • Spring配置方式
    • XML配置方式
    • properties配置方式
    • annotation配置方式
  • Java API配置方式

45.Dubbo 核心的配置有哪些?

在这里插入图片描述
配置之间的关系如图:
在这里插入图片描述
参考资料:

https://mp.weixin.qq.com/s?__biz=MzI3ODcxMzQzMw==&mid=2247487261&idx=1&sn=d3dd9825515f2f79f5e44def251a8e5c&chksm=eb538a2bdc24033dd8c1ceba703688647fb2d7cdcda9b100fbaf60b65a4114ede7c444d087d6&mpshare=1&scene=1&srcid=1002YAyPx7X6QOYB5ZGXyMlP#rd

https://zhuanlan.zhihu.com/p/88889187

https://blog.csdn.net/u012796139/article/details/107171584

兄弟姐妹们,年前拼一拼,搏一搏,年后换一份工作,单车变摩托。

感谢您的阅读,如果本篇博客对您有一定的帮助,大家记得留言+点赞+收藏哈。~~

猜你喜欢

转载自blog.csdn.net/zmh458/article/details/122333255