Dubbo基础
👾
本文大部分内容收集自网络。侵删。
RPC
为什么要有RPC?
http接口是在接口不多、系统与系统交互较少的情况下,解决信息孤岛初期常使用的一种通信手段;优点就是简单、直接、开发方便。利用现成的http协议进行传输。但是如果是一个大型的网站,内部子系统较多、接口非常多的情况下,RPC框架的好处就显示出来了,首先就是长链接,不必每次通信都要像http一样去3次握手什么的,减少了网络开销;其次就是RPC框架一般都有注册中心,有丰富的监控管理;发布、下线接口、动态扩展等,对调用方来说是无感知、统一化的操作。
第三个来说就是安全性。最后就是最近流行的服务化架构、服务化治理,RPC框架是一个强力的支撑。
socket只是一个简单的网络通信方式,只是创建通信双方的通信通道,而要实现rpc的功能,还需要对其进行封装,以实现更多的功能。
RPC一般配合netty框架、spring自定义注解来编写轻量级框架,其实netty内部是封装了socket的,较新的jdk的IO一般是NIO,即非阻塞IO,在高并发网站中,RPC的优势会很明显。
什么是RPC?
RPC(Remote Procedure Call Protocol)远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。简言之,RPC使得程序能够像访问本地系统资源一样,去访问远端系统资源。比较关键的一些方面包括:通讯协议、序列化、资源(接口)描述、服务框架、性能、语言支持等。
简单的说,RPC就是从一台机器(客户端)上通过参数传递的方式调用另一台机器(服务器)上的一个函数或方法(可以统称为服务)并得到返回的结果。
PRC架构组件
一个基本的RPC架构里面应该至少包含以下4个组件:
1、客户端(Client):服务调用方(服务消费者)
2、客户端存根(Client Stub):存放服务端地址信息,将客户端的请求参数数据信息打包成网络消息,再通过网络传输发送给服务端
3、服务端存根(Server Stub):接收客户端发送过来的请求消息并进行解包,然后再调用本地服务进行处理
4、服务端(Server):服务的真正提供者
具体调用过程:
1、服务消费者(client客户端)通过调用本地服务的方式调用需要消费的服务;
2、客户端存根(client stub)接收到调用请求后负责将方法、入参等信息序列化(组装)成能够进行网络传输的消息体;
3、客户端存根(client stub)找到远程的服务地址,并且将消息通过网络发送给服务端;
4、服务端存根(server stub)收到消息后进行解码(反序列化操作);
5、服务端存根(server stub)根据解码结果调用本地的服务进行相关处理;
6、本地服务执行具体业务逻辑并将处理结果返回给服务端存根(server stub);
7、服务端存根(server stub)将返回结果重新打包成消息(序列化)并通过网络发送至消费方;
8、客户端存根(client stub)接收到消息,并进行解码(反序列化);
9、服务消费方得到最终结果;
而RPC框架的实现目标则是将上面的第2-10步完好地封装起来,也就是把调用、编码/解码的过程给封装起来,让 用户感觉上像调用本地服务一样的调用远程服务。
RPC和SOA、SOAP、REST的区别
1、REST
可以看着是HTTP协议的一种直接应用,默认基于JSON作为传输格式,使用简单,学习成本低效率高,但是安全性较低。
2、SOAP
SOAP是一种数据交换协议规范,是一种轻量的、简单的、基于XML的协议的规范。而SOAP可以看着是一个重量级的协议,基于XML、SOAP在安全方面是通过使用XML-Security和XML-Signature两个规范组成了WS-Security来实现安全控制的,当前已经得到了各个厂商的支持 。
它有什么优点?简单总结为:易用、灵活、跨语言、跨平台。
3、SOA
面向服务架构,它可以根据需求通过网络对松散耦合的粗粒度应用组件进行分布式部署、组合和使用。服务层是SOA的基础,可以直接被应用调用,从而有效控制系统中与软件代理交互的人为依赖性。
SOA是一种粗粒度、松耦合服务架构,服务之间通过简单、精确定义接口进行通讯,不涉及底层编程接口和通讯模型。SOA可以看作是B/S模型、XML(标准通用标记语言的子集)/Web Service技术之后的自然延伸。
4、REST 和 SOAP、RPC 有何区别呢?
没什么太大区别,他们的本质都是提供可支持分布式的基础服务,最大的区别在于他们各自的的特点所带来的不同应用场景 。
RPC框架需要解决的问题?
1、如何确定客户端和服务端之间的通信协议?
2、如何更高效地进行网络通信?
3、服务端提供的服务如何暴露给客户端?
4、客户端如何发现这些暴露的服务?
5、如何更高效地对请求对象和响应结果进行序列化和反序列化操作?
RPC的实现基础?
1、需要有非常高效的网络通信,比如一般选择Netty作为网络通信框架;
2、需要有比较高效的序列化框架,比如谷歌的Protobuf序列化框架;
3、可靠的寻址方式(主要是提供服务的发现),比如可以使用Zookeeper来注册服务等等;
4、如果是带会话(状态)的RPC调用,还需要有会话和状态保持的功能;
RPC使用了哪些关键技术?
1、动态代理
生成Client Stub(客户端存根)和Server Stub(服务端存根)的时候需要用到Java动态代理技术,可以使用JDK提供的原生的动态代理机制,也可以使用开源的:CGLib代理,Javassist字节码生成技术。
2、序列化和反序列化
在网络中,所有的数据都将会被转化为字节进行传送,所以为了能够使参数对象在网络中进行传输,需要对这些参数进行序列化和反序列化操作。
序列化:把对象转换为字节序列的过程称为对象的序列化,也就是编码的过程。反序列化:把字节序列恢复为对象的过程称为对象的反序列化,也就是解码的过程。 目前比较高效的开源序列化框架:如Kryo、FastJson和Protobuf等。
反序列化:把字节序列恢复为对象的过程称为对象的反序列化,也就是解码的过程。 目前比较高效的开源序列化框架:如Kryo、FastJson和Protobuf等。
3、NIO通信
出于并发性能的考虑,传统的阻塞式IO显然不太合适,因此我们需要异步的IO,即NIO。Java提供了NIO的解决方案,Java 7 也提供了更优秀的NIO.2支持。可以选择Netty或者MINA来解决NIO数据传输的问题。
4、服务注册中心
可选:Redis、Zookeeper、Consul 、Etcd。一般使用ZooKeeper提供服务注册与发现功能,解决单点故障以及分布式部署的问题(注册中心)。
主流RPC框架有哪些?
1、RMI
利用java.rmi包实现,基于Java远程方法协议(Java Remote Method Protocol) 和java的原生序列化。
2、Hessian
是一个轻量级的remoting onhttp工具,使用简单的方法提供了RMI的功能。 基于HTTP协议,采用二进制编解码。
3、protobuf-rpc-pro
是一个Java类库,提供了基于 Google 的 Protocol Buffers 协议的远程方法调用的框架。基于Netty 底层的 NIO 技术。支持 TCP 重用/ keep-alive、SSL加密、RPC 调用取消操作、嵌入式日志等功能。
4、Thrift
是一种可伸缩的跨语言服务的软件框架。它拥有功能强大的代码生成引擎,无缝地支持C + +,C#,Java,Python和PHP和Ruby。thrift允许你定义一个描述文件,描述数据类型和服务接口。
依据该文件,编译器方便地生成RPC客户端和服务器通信代码。
最初由facebook开发用做系统内个语言之间的RPC通信,2007年由facebook贡献到apache基金 ,现在是apache下的opensource之一 。支持多种语言之间的RPC方式的通信:php语言client可以构造一个对象,调用相应的服务方法来调用java语言的服务,跨越语言的C/S RPC调用。底层通讯基于SOCKET。
5、Avro
出自Hadoop之父Doug Cutting, 在Thrift已经相当流行的情况下推出Avro的目标不仅是提供一套类似Thrift的通讯中间件,更是要建立一个新的,标准性的云计算的数据交换和存储的Protocol。支持HTTP,TCP两种协议。
6、Dubbo
Dubbo是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的RPC实现服务的输出和输入功能,可以和Spring框架无缝集成。
Dubbo
为什么要用Dubbo?
随着服务化的进一步发展,服务越来越多,服务之间的调用和依赖关系也越来越复杂,诞生了面向服务的架构体系(SOA),也因此衍生出了一系列相应的技术,如对服务提供、服务调用、连接处理、通信协议、序列化方式、服务发现、服务路由、日志输出等行为进行封装的服务框架。就这样为分布式系统的服务治理框架就出现了,Dubbo 也就这样产生了。
Dubbo架构
注意
需要会画上面这个图!
Container 服务运行的容器
用来运行服务的。
Provider 服务提供者
service,实际执行业务逻辑的服务层。
Consumer 服务消费者
用来调用service的,不关注service具体实现的应用层。
Registry 注册中心
存储Provider,consumer信息的中介。
Monitor
Dubbo负责收集服务调用信息的监控中心。
大致流程:
首先服务提供者 Provider 启动然后向注册中心注册自己所能提供的服务。
服务消费者 Consumer 启动向注册中心订阅自己所需的服务。然后注册中心将提供者元信息通知给 Consumer, 之后 Consumer 因为已经从注册中心获取提供者的地址,因此可以通过负载均衡选择一个 Provider 直接调用 。
之后服务提供方元数据变更的话注册中心会把变更推送给服务消费者。
服务提供者和消费者都会在内存中记录着调用的次数和时间,然后定时的发送统计数据到监控中心。
Dubbo分层架构
Dubbo大的三层分别为 Business(业务层)、RPC 层、Remoting层,也可以分为 API 层和 SPI 层。
分为大三层其实就是和我们知道的网络分层一样的意思,只有层次分明,职责边界清晰才能更好的扩展。
而分 API 层和 SPI 层这是 Dubbo 成功的一点,采用微内核设计+SPI扩展,使得有特殊需求的接入方可以自定义扩展,做定制的二次开发。
每一层的作用如下:
- Service,业务层,就是咱们开发的业务逻辑层。
- Config,配置层,主要围绕 ServiceConfig 和 ReferenceConfig,初始化配置信息。
- Proxy,代理层,服务提供者和消费者都会生成一个代理类,使得服务接口透明化,代理层做远程调用和返回结果。
- Register,注册层,封装了服务注册和发现。
- Cluster,路由和集群容错层,负责选取具体调用的节点,处理特殊的调用要求和负责远程调用失败的容错措施。
- Monitor,监控层,负责监控统计调用时间和次数。
- Portocol,远程调用层,主要是封装 RPC 调用,主要负责管理 Invoker,Invoker代表一个抽象封装了的执行体。
- Exchange,信息交换层,用来封装请求响应模型,同步转异步。
- Transport,网络传输层,抽象了网络传输的统一接口,这样用户想用 Netty 就用 Netty,想用 Mina 就用 Mina(默认也推荐使用netty作为通信框架,还有mina)
- Serialize,序列化层,将数据序列化成二进制流,当然也做反序列化。
Dubbo的使用场景有哪些?
透明化的远程方法调用:就像调用本地方法一样调用远程方法,只需简单配置,没有任何API侵入。
软负载均衡及容错机制:可在内网替代 F5 等硬件负载均衡器,降低成本,减少单点。
服务自动注册与发现:不再需要写死服务提供方地址,注册中心基于接口名查询服务提供者的IP地址,并且能够平滑添加或删除服务提供者。
Dubbo核心功能有哪些?
Remoting:网络通信框架,提供对多种NIO框架抽象封装,包括“同步转异步”和“请求-响应”模式的信息交换方式。
Cluster:服务框架,提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集群支持。
Registry:服务注册,基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透明,使服务提供方可以平滑增加或减少机器。
Dubbo和Spring Cloud有什么关系?
Dubbo是SOA时代的产物,它的关注点主要在于服务的调用,流量分发、流量监控和熔断。而Spring Cloud诞生于微服务架构时代,考虑的是微服务治理的方方面面,另外由于依托了Spring、Spring Boot的优势之上,两个框架在开始目标就不一致,Dubbo定位服务治理,Spring Cloud是打造一个生态。
Dubbo和Spring Cloud有什么哪些区别?
Dubbo底层是使用Netty这样的NIO框架,是基于TCP协议传输的,配合以Hession序列化完成 RPC通信。
Spring Cloud是基于Http协议Rest接口调用远程过程的通信,相对来说Http请求会有更大的报文,占的带宽也会更多。但是 REST相比RPC更为灵活,服务提供方和调用方的依赖只依靠一纸契约,不存在代码级别的强依赖,这在强调快速演化的微服务环境下,显得更为合适,至于注重通信速度还是方便灵活性,具体情况具体考虑。
Dubbo支持哪些协议,它们的优缺点有哪些?
Dubbo:单一长连接和NIO异步通讯,适合大并发小数据量的服务调用,以及消费者远大于提供者。传输协议TCP,异步 Hessian序列化。Dubbo推荐使用dubbo协议。
RMI: 采用JDK标准的RMI协议实现,传输参数和返回参数对象需要实现 Serializable 接口,使用 Java 标准序列化机制,使用阻塞式短连接,传输数据包大小混合,消费者和提供者个数差不多,可传文件,传输协议TCP。 多个短连接 TCP协议传输,同步传输,适用常规的远程服务调用和RMI互操作。在依赖低版本的Common-Collections 包,Java 序列化存在安全漏洞。
WebService:基于WebService的远程调用协议,集成CXF实现,提供和原生WebService的互操作。多个短连接,基于 HTTP 传输,同步传输,适用系统集成和跨语言调用。
HTTP: 基于 Http 表单提交的远程调用协议,使用Spring的HttpInvoke 实现。多个短连接,传输协议HTTP,传入参数大小混合,提供者个数多于消费者,需要给应用程序和浏览器JS调用。
Hessian:集成 Hessian 服务,基于 HTTP 通讯,采用 Servlet暴露服务,Dubbo 内嵌 Jetty 作为服务器时默认实现,提供与 Hession 服务互操作。多个短连接,同步 HTTP 传输,Hessian 序列化,传入参数较大,提供者大于消费者,提供者压力较大,可传文件。
Memcache:基于Memcache实现的RPC协议。
Redis:基于Redis实现的RPC协议。
服务暴露的流程?
服务的暴露起始于 Spring IOC 容器刷新完毕之后,会根据配置参数组装成 URL, 然后根据 URL 的参数来进行本地或者远程调用。
会通过 proxyFactory.getInvoker,利用 javassist 来进行动态代理,封装真的实现类,然后再通过 URL 参数选择对应的协议来进行 protocol.export,默认是 Dubbo 协议。
在第一次暴露的时候会调用 createServer 来创建 Server,默认是 NettyServer。
然后将 export 得到的 exporter 存入一个 Map 中,供之后的远程调用查找,然后会向注册中心注册提供者的信息。
基本上就是这么个流程,说了这些差不多了,太细的谁都记住不。
服务引入的流程?
服务的引入时机有两种,第一种是饿汉式,第二种是懒汉式。
饿汉式就是加载完毕就会引入,懒汉式是只有当这个服务被注入到其他类中时启动引入流程,默认是懒汉式。
会先根据配置参数组装成 URL ,一般而言我们都会配置的注册中心,所以会构建 RegistryDirectory 向注册中心注册消费者的信息,并且订阅提供者、配置、路由等节点。
得知提供者的信息之后会进入 Dubbo 协议的引入,会创建 Invoker ,期间会包含 NettyClient,来进行远程通信,最后通过 Cluster 来包装 Invoker,默认是 FailoverCluster,最终返回代理类。
说这么多差不多了,关键的点都提到了。
切忌不要太过细,不要把你知道的都说了,这样会抓不住重点,比如上面的流程你要插入,引入的三种方式:本地引入、直连远程引入、通过注册中心引入。
然后再分别说本地引入怎样的,就会很乱,所以面试的时候是需要删减的,要直击重点。
服务调用的流程?
调用某个接口的方法会调用之前生成的代理类,然后会从 cluster 中经过路由的过滤、负载均衡机制选择一个 invoker 发起远程调用,此时会记录此请求和请求的 ID 等待服务端的响应。
服务端接受请求之后会通过参数找到之前暴露存储的 map,得到相应的 exporter ,然后最终调用真正的实现类,再组装好结果返回,这个响应会带上之前请求的 ID。
消费者收到这个响应之后会通过 ID 去找之前记录的请求,然后找到请求之后将响应塞到对应的 Future 中,唤醒等待的线程,最后消费者得到响应,一个流程完毕。
关键的就是 cluster、路由、负载均衡,然后 Dubbo 默认是异步的,所以请求和响应是如何对应上的。
知道什么是 SPI 嘛?
从上面的回答中,不论是从 Dubbo 协议,还是 cluster ,什么 export 方法等等无处不是 SPI 的影子,所以如果是问 Dubbo 方面的问题,问 SPI 是毋庸置疑的,因为源码里 SPI 无处不在,而且 SPI 也是 Dubbo 可扩展性的基石。
所以这个题目没什么套路,直接答就行。
SPI 是 Service Provider Interface,主要用于框架中,框架定义好接口,不同的使用者有不同的需求,因此需要有不同的实现,而 SPI 就通过定义一个特定的位置,Java SPI 约定在 Classpath 下的 META-INF/services/ 目录里创建一个以服务接口命名的文件,然后文件里面记录的是此 jar 包提供的具体实现类的全限定名。
所以就可以通过接口找到对应的文件,获取具体的实现类然后加载即可,做到了灵活的替换具体的实现类。
为什么 Dubbo 不用 JDK 的 SPI,而是要自己实现?
问这个问题就是看你有没有深入的了解,或者自己思考过,不是死板的看源码,或者看一些知识点。
很多点是要思考的,不是书上说什么就是什么,你要知道这样做的理由,有什么好处和坏处,这很容易看出一个人是死记硬背还是有自己的思考。
答:因为 Java SPI 在查找扩展实现类的时候遍历 SPI 的配置文件并且将实现类全部实例化,假设一个实现类初始化过程比较消耗资源且耗时,但是你的代码里面又用不上它,这就产生了资源的浪费。
因此 Dubbo 就自己实现了一个 SPI,给每个实现类配了个名字,通过名字去文件里面找到对应的实现类全限定名然后加载实例化,按需加载。
Dubbo 为什么默认用 Javassist
上面你回答 Dubbo 用 Javassist 动态代理,所以很可能会问你为什么要用这个代理,可能还会引申出 JDK 的动态代理、ASM、CGLIB。
很简单,就是快,且字节码生成方便。
ASM 比 Javassist 更快,但是没有快一个数量级,而Javassist 只需用字符串拼接就可以生成字节码,而 ASM 需要手工生成,成本较高,比较麻烦。
🔴Dubbo 异步转同步如何实现的
服务调用是阻塞的吗?
默认是阻塞的,可以异步调用,没有返回值的可以这么做。 Dubbo是基于NIO的非阻塞实现并行调用,客户端不需要启动多线程即可完成并行调用多个远程服务,相对多线程开销较小,异步调用会返回一个Future对象。
Dubbo有哪些注册中心?
Multicast注册中心:Multicast 注册中心不需要任何中心节点,只要广播地址,就能进行服务注册和发现,基于网络中组播传输实现。
Zookeeper注册中心(推荐使用):基于分布式协调系统Zookeeper 实现,采用Zookeeper的watch机制实现数据变更。
Redis注册中心:基于Redis实现,采用key/map存储,key存储服务名和类型,map中key存储服务url,value服务过期时间。基于Redis的发布/订阅模式通知数据变更。
Simple注册中心。
默认使用什么序列化框架,你知道的还有哪些?
推荐使用Hessian序列化,还有Duddo、FastJson、Java自带序列化。
服务提供者能实现失效踢出是什么原理?
服务失效踢出基于zookeeper 的临时节点原理。
服务上线怎么不影响旧版本?
采用多版本开发。多个不同版本的服务注册到注册中心,版本号不同的服务相互间不引用。这个和服务分组的概念有一点类似。
Dubbo服务降级怎么做?
方法1:在dubbo:reference
中设置 mock=“return null”
。
方法2:在dubbo:reference
中设置 mock=“true”
,然后再跟接口同一个路径下实现一个 Mock 类,命名规则是 “接口名称+Mock” 后缀。然后在Mock类里实现自己的降级逻辑。
Dubbo Monitor实现原理?
Consumer端在发起调用之前会先走filter链;provider端在接收到请求时也是先走filter链,然后才进行真正的业务逻辑处理。
默认情况下,在consumer和provider的filter链中都会有Monitorfilter。
1、MonitorFilter向DubboMonitor 发送数据
2、DubboMonitor将数据进行聚合后(默认聚合1min中的统计数据)暂存到ConcurrentMap<Statistics, AtomicReference> statisticsMap,然后使用一个含有3个线程(线程名字:DubboMonitorSendTimer)的线程池每隔1min钟,调用SimpleMonitorService遍历发送statisticsMap 中的统计数据,每发送完毕一个,就重置当前的Statistics的AtomicReference
3、SimpleMonitorService将这些聚合数据塞入BlockingQueue queue中(队列大写为100000)
4、SimpleMonitorService使用一个后台线程(线程名为:DubboMonitorAsyncWriteLogThread)将queue中的数据写入文件(该线程以死循环的形式来写)
5、SimpleMonitorService 还会使用一个含有 1 个线程(线程名字:DubboMonitorTimer)的线程池每隔5min钟,将文件中的统计数据画成图表
Dubbo用到哪些设计模式?
Dubbo框架在初始化和通信过程中使用了多种设计模式,可灵活控制类加载、权限控制等功能。
工厂模式
Provider在export服务时,会调用ServiceConfig的export方法。ServiceConfig中有个字段:
private static final Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
Dubbo里有很多这种代码。这也是一种工厂模式,只是实现类的获取采用了JDKSPI
的机制。这么实现的优点是可扩展性强,想要扩展实现,只需要在classpath下增加个文件就可以了,代码零侵入。另外,像上面的Adaptive
实现,可以做到调用时动态决定调用哪个实现,但是由于这种实现采用了动态代理,会造成代码调试比较麻烦,需要分析出实际调用的实现类。
装饰器模式
Dubbo在启动和调用阶段都大量使用了装饰器模式。以 Provider
提供的调用链为例,具体的调用链代码是在ProtocolFilterWrapper
的buildInvokerChain
完成的,具体是将注解中含有group=provider
的Filter
实现,按照order
排序,最后的调用顺序是:
EchoFilter -> ClassLoaderFilter -> GenericFilter -> ContextFilter ->
ExecuteLimitFilter -> TraceFilter -> TimeoutFilter -> MonitorFilter -> ExceptionFilter
更确切地说,这里是装饰器和责任链模式的混合使用。例如,EchoFilter
的作用是判断是否是回声测试请求,是的话直接返回内容,这是一种责任链的体现。而像ClassLoaderFilter
则只是在主功能上添加了功能,更改当前线程的ClassLoader
,这是典型的装饰器模式。
观察者模式
Dubbo的Provider启动时,需要与注册中心交互,先注册自己的服务,再订阅自己的服务,订阅时,采用了观察者模式,开启一个listener。注册中心会每5秒定时检查是否有服务更新,如果有更新,向该服务的提供者发送一个notify消息,provider接受到notify消息后,即运行NotifyListener的notify方法,执行监听器方法。
动态代理模式
Dubbo扩展JDK SPI的类ExtensionLoader的Adaptive实现是典型的动态代理实现。Dubbo需要灵活地控制实现类,即在调用阶段动态地根据参数决定调用哪个实现类,所以采用先生成代理类的方法,能够做到灵活的调用。生成代理类的代码是ExtensionLoader的createAdaptiveExtensionClassCode方法。代理类的主要逻辑是,获取URL参数中指定参数的值作为获取实现类的key。
Dubbo配置文件是如何加载到Spring中的?
Spring容器在启动的时候,会读取到Spring默认的一些schema以及Dubbo自定义的schema,每个schema都会对应一个自己的NamespaceHandler
,NamespaceHandler
里面通过BeanDefinitionParser
来解析配置信息并转化为需要加载的 bean 对象。
Dubbo SPI和Java SPI区别?
JDK SPI
JDK标准的SPI会一次性加载所有的扩展实现,如果有的扩展很耗时,但也没用上,很浪费资源。 所以只希望加载某个的实现,就不现实了。
DUBBO SPI
- 对 Dubbo进行扩展,不需要改动Dubbo的源码
- 延迟加载,可以一次只加载自己想要加载的扩展实现。
- 增加了对扩展点IOC和AOP的支持,一个扩展点可以直接setter注入其它扩展点。
- Dubbo的扩展机制能很好的支持第三方IoC容器,默认支持Spring Bean。
Dubbo支持分布式事务吗?
目前暂时不支持,可与通过tcc-transaction框架实现
介绍:tcc-transaction 是开源的TCC补偿性分布式事务框架
Git 地址:https://github.com/changmingxie/tcc-transaction
TCC-Transaction 通过Dubbo隐式传参的功能,避免自己对业务代码的入侵。
参考:dubbo分布式事务
Dubbo可以对结果进行缓存吗?
为了提高数据访问的速度。Dubbo提供了声明式缓存,以减少用户加缓存的工作量
<dubbo:reference cache="true" />
其实比普通的配置文件就多了一个标签 cache=“true”
Dubbo telnet命令能做什么?
dubbo服务发布之后,我们可以利用telnet命令进行调试、管理。Dubbo2.0.5以上版本服务提供端口支持telnet命令连接服务
telnet localhost20880//键入回车进入Dubbo命令模式。
查看服务列表:
Dubbo如何优雅停机?
Dubbo是通过JDK的ShutdownHook来完成优雅停机的,所以如果使用kill -9 PID等强制关闭指令,是不会执行优雅停机的,只有通过kill PID 时,才会执行。
Dubbo和Dubbox之间的区别?
Dubbox是继Dubbo停止维护后,当当网基于Dubbo做的一个扩展项目,如加了服务可Restful调用,更新了开源组件等。
Dubbo的注册中心集群挂掉,发布者和订阅者之间还能通信么?
可以通讯。启动Dubbo 时,消费者会从Zookeeper拉取注册的生产者的地址接口等数据,缓存在本地。每次调用时,按照本地存储的地址进行调用。
Dubbo集群提供了哪些负载均衡策略?
Random LoadBalance(默认): 随机选取提供者策略,有利于动态调整提供者权重。截面碰撞率高,调用次数越多,分布越均匀。
RoundRobin LoadBalance: 轮循选取提供者策略,平均分布,但是存在请求累积的问题。
LeastActive LoadBalance: 最少活跃调用策略,解决慢提供者接收更少的请求。
ConstantHash LoadBalance: 一致性Hash策略,使相同参数请求总是发到同一提供者,一台机器宕机,可以基于虚拟节点,分摊至其他提供者,避免引起提供者的剧烈变动。
Dubbo的集群容错方案有哪些?
Failover Cluster(默认):失败自动切换,当出现失败,重试其它服务器。通常用于读操作,但重试会带来更长延迟。
Failfast Cluster:快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。
Failsafe Cluster:失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。
Failback Cluster:失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
Forking Cluster:并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks=″2″
来设置最大并行数。
Broadcast Cluster:广播调用所有提供者,逐个调用,任意一台报错则报错 。通常用于通知所有提供者更新缓存或日志等本地资源信息。
Dubbo超时设置有哪些方式?
Dubbo超时设置有两种方式:
服务提供者端设置超时时间,在Dubbo的用户文档中,推荐如果能在服务端多配置就尽量多配置,因为服务提供者比消费者更清楚自己提供的服务特性。
服务消费者端设置超时时间,如果在消费者端设置了超时时间,以消费者端为主,即优先级更高。
因为服务调用方设置超时时间控制性更灵活。如果消费方超时,服务端线程不会定制,会产生警告。
如果让你设计一个 RPC 框架,如何设计?
面试官都很喜欢问这类问题,来考验候选人的设计能力,和平日有无全方面的了解过一个框架。
如果你平时没有思考,没有往这方面想过答出来的东西就会没有条理性,会显得杂乱无章,不过你也不用慌张,不用想的很全面,答的很细致,没有必要,面试官要的是那些关键的重点。
你可以从底层向上开始说起。
首先需要实现高性能的网络传输,可以采用 Netty 来实现,不用自己重复造轮子,然后需要自定义协议,毕竟远程交互都需要遵循一定的协议,然后还需要定义好序列化协议,网络的传输毕竟都是二进制流传输的。
然后可以搞一套描述服务的语言,即 IDL(Interface description language),让所有的服务都用 IDL 定义,再由框架转换为特定编程语言的接口,这样就能跨语言了。
此时最近基本的功能已经有了,但是只是最基础的,工业级的话首先得易用,所以框架需要把上述的细节对使用者进行屏蔽,让他们感觉不到本地调用和远程调用的区别,所以需要代理实现。
然后还需要实现集群功能,因此的要服务发现、注册等功能,所以需要注册中心,当然细节还是需要屏蔽的。
最后还需要一个完善的监控机制,埋点上报调用情况等等,便于运维。
这样一个 RPC 框架的雏形就差不多了。
Dubbo使用过程中都遇到了些什么问题?
- 在注册中心找不到对应的服务。检查service实现类是否添加了
@service
注解 - 无法连接到注册中心,检查配置文件中的对应的注册中心
IP
是否正确。
参考
- 0很棒
- 0不错
- 0一般
- 0???