Dubbo系列-Dubbo常见面试题
Posted coding++
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Dubbo系列-Dubbo常见面试题相关的知识,希望对你有一定的参考价值。
开始你的表演:
知道什么是 RPC 么?
一般面试官会以这样的问题来切入、热场,毕面试也是循序渐进的过程,所以你也不用太心急一开始就芭芭拉说一堆,要抓住关键点简单阐述先。
而且面试官能从这个问题鉴定出你平日的工作内容会不会连 RPC 都没接触过,会不会就只是一条龙的 Spring MVC ?
确实有很多同学没接触过 RPC ,也很正常比如一些外包或者一些小项目都接触不到的,不过平日接触不到和你不知道这个东西是两个概念。
能从侧面反映出这个人工作之余应该不怎么学习,连 RPC 都不知道,所以怎么都说不过去,基本上要凉凉,对你的初始印象就差了,除非你能从后面有亮眼的表现。
答:RPC 就是 Remote Procedure Call,远程过程调用,它相对应的是本地过程调用。
那为什么要有 RPC,HTTP 不好么?
这时候面试官就开始追问了。
这个问题其实很有意思,有些面试官可能自己不太清楚,然后以为自己很清楚,所以问出这个问题,还有一种是真的清楚,问这个问题是为了让你跳坑里。
因为 RPC 和 HTTP 就不是一个层级的东西,所以严格意义上这两个没有可比性,也不应该来作比较,而题目问的就是把这两个作为比较了。
HTTP 只是传输协议,协议只是规范了一定的交流格式,而且 RPC 是早于 HTTP 的,所以真要问也是问有 RPC 为什么还要 HTTP。
RPC 对比的是本地过程调用,是用来作为分布式系统之间的通信,它可以用 HTTP 来传输,也可以基于 TCP 自定义协议传输。
所以你要先提出这两个不是一个层级的东西,没有可比性,然后再表现一下,可以说 HTTP 协议比较冗余,所以 RPC 大多都是基于 TCP 自定义协议,定制化的才是最适合自己的。
当然也有基于 HTTP 协议的 RPC 框架,毕竟 HTTP 是公开的协议,比较通用,像 HTTP2 已经做了相应的压缩了,而且系统之间的调用都在内网,所以说影响也不会很大。
这波回答下来,面试官会觉得你有点东西,开始对你有点兴趣了,要开始深入你了。
看过源码,那说下服务暴露的流程?
服务的暴露起始于 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。
所以这也是个注意点,如果你不太清楚的话上面的回答就不要扯到动态代理了,如果清楚的话那肯定得提,来诱导面试官来问你动态代理方面的问题,这很关键。
面试官是需要诱导的,毕竟他也想知道你优秀的方面到底有多优秀,你也取长补短,双赢双赢。
来回答下为什么用 Javassist,很简单,就是快,且字节码生成方便。
ASM 比 Javassist 更快,但是没有快一个数量级,而Javassist 只需用字符串拼接就可以生成字节码,而 ASM 需要手工生成,成本较高,比较麻烦
以上是关于Dubbo系列-Dubbo常见面试题的主要内容,如果未能解决你的问题,请参考以下文章