有情怀,有干货,微信搜索【三太子敖丙】关注这个不同的程序员。java
本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试完整考点、资料以及个人系列文章。git
Dubbo 总体介绍的差很少了,今天就开始面试环节了,我会列举一些常见的 Dubbo 面试题,只会抓着重的,一些太简单的我就不提了。程序员
不只仅给你面试题的答案,也会剖析面试官问这个问题的缘由,也就是他的心里活动。github
想从你这里问出什么?想要什么答案?想挖什么坑给你跳?web
通常面试官会以这样的问题来切入、热场,毕面试也是按部就班的过程,因此你也不用太心急一开始就芭芭拉说一堆,要抓住关键点简单阐述先。面试
并且面试官能从这个问题鉴定出你平日的工做内容会不会连 RPC 都没接触过,会不会就只是一条龙的 Spring MVC ?编程
确实有不少同窗没接触过 RPC ,也很正常好比一些外包或者一些小项目都接触不到的,不过平日接触不到和你不知道这个东西是两个概念。数组
能从侧面反映出这我的工做之余应该不怎么学习,连 RPC 都不知道,因此怎么都说不过去,基本上要凉凉,对你的初始印象就差了,除非你能从后面有亮眼的表现。微信
答:RPC 就是 Remote Procedure Call,远程过程调用,它相对应的是本地过程调用。网络
这时候面试官就开始追问了。
这个问题其实颇有意思,有些面试官可能本身不太清楚,而后觉得本身很清楚,因此问出这个问题,还有一种是真的清楚,问这个问题是为了让你跳坑里。
由于 RPC 和 HTTP 就不是一个层级的东西,因此严格意义上这两个没有可比性,也不该该来做比较,而题目问的就是把这两个做为比较了。
HTTP 只是传输协议,协议只是规范了必定的交流格式,并且 RPC 是早于 HTTP 的,因此真要问也是问有 RPC 为何还要 HTTP。
RPC 对比的是本地过程调用,是用来做为分布式系统之间的通讯,它能够用 HTTP 来传输,也能够基于 TCP 自定义协议传输。
因此你要先提出这两个不是一个层级的东西,没有可比性,而后再表现一下,能够说 HTTP 协议比较冗余,因此 RPC 大多都是基于 TCP 自定义协议,定制化的才是最适合本身的。
固然也有基于 HTTP 协议的 RPC 框架,毕竟 HTTP 是公开的协议,比较通用,像 HTTP2 已经作了相应的压缩了,并且系统之间的调用都在内网,因此说影响也不会很大。
这波回答下来,面试官会以为你有点东西,开始对你有点兴趣了,要开始深刻你了。
面试官会先问个大点的问题,而后从你的回答中找到一些突破口来深刻问,因此这个问题其实挺开放性的,你能够从历史的发展来答,也能够从总体架构来答。
若是从历史发展的角度来答,说明你平日里也是挺关注一些开源软件的,侧面也能体现你的对开源的拥抱。
若是从整体架构答,毋庸置疑确定也是能够的,建议先浅显的说,等着追问。
历史发展,这个其实丙以前文章已经提到了:
Dubbo 是阿里巴巴开源的一个基于 Java 的 RPC 框架,中间沉寂了一段时间,但在 2017 年阿里巴巴又重启了对 Dubbo 维护。
而且在 2018 年和 当当的 Dubbox 进行了合并,进入 Apache 孵化器,在 2019 年毕业正式成为 Apache 顶级项目。
目前 Dubbo 社区主力维护的是 2.6.x 和 2.7.x 两大版本,2.6.x 版本主要是 bug 修复和少许功能加强为准,是稳定版本。
2.7.5 版本的发布被 Dubbo 认为是里程碑式的版本发布,支持 gRPC,而且性能提高了 30%(这里不了解gRPC 和为何性能提高的话就别说了,别给本身挖坑)。
最新的 3.0 版本往云原生方向上探索着。
注意了,若是对历史各个版本不太熟,也不知道最新的版本要干啥就别往这方向答了,运气好点就是面试官本身也不太了解,他可能不会问,运气背点就追问了。
整体架构,上面也提到了先浅显的说,等追问,由于面试官若是懂,他确定会问深刻,若是不懂你芭芭拉一堆他无感的。
你就简单的提一下如今这几个角色。
节点 | 角色说明 |
---|---|
Consumer | 须要调用远程服务的服务消费方 |
Registry | 注册中心 |
Provider | 服务提供方 |
Container | 服务运行的容器 |
Monitor | 监控中心 |
好比, Dubbo 整体分了以上这么几个角色,分别的做用是xxxx。
这里停顿下看下面试官的反应,若是没搭话,就继续说大体的流程。
首先服务提供者 Provider 启动而后向注册中心注册本身所能提供的服务。
服务消费者 Consumer 启动向注册中心订阅本身所需的服务。而后注册中心将提供者元信息通知给 Consumer, 以后 Consumer 由于已经从注册中心获取提供者的地址,所以能够经过负载均衡选择一个 Provider 直接调用 。
以后服务提供方元数据变动的话注册中心会把变动推送给服务消费者。
服务提供者和消费者都会在内存中记录着调用的次数和时间,而后定时的发送统计数据到监控中心。
到这基本上就差很少了,若是以前看过丙的 Dubbo 系列文章的话,那就算看过源码了,确定对一系列过程很清晰了,因此在适当的时机能够说本身看过 Dubbo 源码。
众所周知,看过源码确定是加分项,因此这点是要提的。
面试官一听,好家伙看过源码是吧,来讲说。
接下来就开始连击了。
服务的暴露起始于 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 默认是异步的,因此请求和响应是如何对应上的。
以后可能还会追问 Dubbo 异步转同步如何实现的之类的,在丙以前文章里面都说了,忘记的同窗能够回去看看。
这又是一个方向了,从上面的回答中,不管是从 Dubbo 协议,仍是 cluster ,什么 export 方法等等无处不是 SPI 的影子,因此若是是问 Dubbo 方面的问题,问 SPI 是毋庸置疑的,由于源码里 SPI 无处不在,并且 SPI 也是 Dubbo 可扩展性的基石。
因此这个题目没什么套路,直接答就行。
SPI 是 Service Provider Interface,主要用于框架中,框架定义好接口,不一样的使用者有不一样的需求,所以须要有不一样的实现,而 SPI 就经过定义一个特定的位置,Java SPI 约定在 Classpath 下的 META-INF/services/ 目录里建立一个以服务接口命名的文件,而后文件里面记录的是此 jar 包提供的具体实现类的全限定名。
因此就能够经过接口找到对应的文件,获取具体的实现类而后加载便可,作到了灵活的替换具体的实现类。
问这个问题就是看你有没有深刻的了解,或者本身思考过,不是死板的看源码,或者看一些知识点。
不少点是要思考的,不是书上说什么就是什么,你要知道这样作的理由,有什么好处和坏处,这很容易看出一我的是死记硬背仍是有本身的思考。
答:由于 Java SPI 在查找扩展实现类的时候遍历 SPI 的配置文件而且将实现类所有实例化,假设一个实现类初始化过程比较消耗资源且耗时,可是你的代码里面又用不上它,这就产生了资源的浪费。
所以 Dubbo 就本身实现了一个 SPI,给每一个实现类配了个名字,经过名字去文件里面找到对应的实现类全限定名而后加载实例化,按需加载。
这答出来就加分了,面试官内心在拍手了,不错不错有点东西。
上面你回答 Dubbo 用 Javassist 动态代理,因此极可能会问你为何要用这个代理,可能还会引伸出 JDK 的动态代理、ASM、CGLIB。
因此这也是个注意点,若是你不太清楚的话上面的回答就不要扯到动态代理了,若是清楚的话那确定得提,来诱导面试官来问你动态代理方面的问题,这很关键。
面试官是须要诱导的,毕竟他也想知道你优秀的方面到底有多优秀,你也取长补短,共赢共赢。
来回答下为何用 Javassist,很简单,就是快,且字节码生成方便。
ASM 比 Javassist 更快,可是没有快一个数量级,而Javassist 只需用字符串拼接就能够生成字节码,而 ASM 须要手工生成,成本较高,比较麻烦。
面试官都很喜欢问这类问题,来考验候选人的设计能力,和平日有无全方面的了解过一个框架。
若是你平时没有思考,没有往这方面想过答出来的东西就会没有条理性,会显得杂乱无章,不过你也不用慌张,不用想的很全面,答的很细致,没有必要,面试官要的是那些关键的重点。
你能够从底层向上开始提及。
首先须要实现高性能的网络传输,能够采用 Netty 来实现,不用本身重复造轮子,而后须要自定义协议,毕竟远程交互都须要遵循必定的协议,而后还须要定义好序列化协议,网络的传输毕竟都是二进制流传输的。
而后能够搞一套描述服务的语言,即 IDL(Interface description language),让全部的服务都用 IDL 定义,再由框架转换为特定编程语言的接口,这样就能跨语言了。
此时最近基本的功能已经有了,可是只是最基础的,工业级的话首先得易用,因此框架须要把上述的细节对使用者进行屏蔽,让他们感受不到本地调用和远程调用的区别,因此须要代理实现。
而后还须要实现集群功能,所以的要服务发现、注册等功能,因此须要注册中心,固然细节仍是须要屏蔽的。
最后还须要一个完善的监控机制,埋点上报调用状况等等,便于运维。
这样一个 RPC 框架的雏形就差很少了。
Dubbo 系列就到此结束了,其实仍是有不少细节的,若是要写确定仍是有不少能够写的。
不过总体脉络都理清楚了,以后的修行仍是得靠你们本身多多努力。
面试题确定不止这一些,面试题是问不完的,真实的面试确定是抓住你回答的点来深挖,因此我也模拟不了,我只能告诉你大体关键点,和揣摩一下面试官的心理活动。
当面试官问你的时候你能够试着去揣摩,看看他到底想要问什么,这很关键。
面试的时候不要慌,你和面试官是平等的,并且面试官不必定你厉害,还有面试有时候就是看运气了,面试失败了也不要气馁,换一家就行了,有时候就是气场不和,这很正常。
加油。
我是敖丙,你知道的越多,你不知道的越多,感谢各位人才的:点赞、收藏和评论,咱们下期见!
文章持续更新,能够微信搜一搜「 三太子敖丙 」第一时间阅读,回复【资料】有我准备的一线大厂面试资料和简历模板,本文 GitHub https://github.com/JavaFamily 已经收录,有大厂面试完整考点,欢迎Star。