参考javaguide里的dubbo面试题。

怎么避免rpc接口重复调用 rpc接口如何测试_java


1.RPC

什么是RPC?

RPC是远程过程调用,Remote Procedure Call。可以实现像本地方法调用那样方便地进行不同服务器之间的方法调用。

RPC的原理是什么?

先画一张图:

怎么避免rpc接口重复调用 rpc接口如何测试_java_02


首先客户端把要调用的方法,类,方法参数等传递给client stub(客户端桩)。然后客户端桩把这些序列化为RpcRequest,并由网络传输给另一台服务器(使用socket或者netty)。然后server stub(服务端桩)把传输过来的RpcRequest进行反序列化,然后把调用的方法,类和参数传给服务端的方法执行得到结果。同理,server stub把结果序列化为RpcResponse,然后通过网络传给客户端,由client stub把结果进行反序列化,得到远程调用的结果。这个过程就好像直接是在服务器本地调用方法一样。

2.Dubbo
什么是Dubbo?
Dubbo是一个分布式服务框架,可以帮我们很方便地实现和管理服务之前的调用。
为什么要用Dubbo?
1.它是一个rpc框架,可以帮我们实现不同服务器之前方法的调用。
2.它的架构比如可选的注册中心和监控中心,可以帮助服务消费者更好的去调用服务,并帮我们理清不同服务之间的调用关系。
3.自带一些负载均衡策略,帮助减缓服务器压力和提高吞吐量。

什么是分布式服务?
分布式服务是面向服务架构的,就是把项目进行拆分为各个子系统,是多个独立的工程,也可以理解为一个服务,比如商品服务,订单服务等,这样便于维护。不同服务是部署在不同的服务器上,如果某个工程并发量和压力大,可以使用集群。(就是同一套代码部署在多个服务器上,然后用负载均衡来使用集群)
为什么要使用分布式服务?
因为拆分为不同服务后,可以解耦,开发人员可以专注于自己负责的服务的开发,提高开发效率。

Dubbo架构:

怎么避免rpc接口重复调用 rpc接口如何测试_服务器_03

Dubbo中的核心角色有哪些?哪些是必须的,哪些是可选的,它们都有什么作用?
有容器container,服务提供者provider,服务消费者consumer,注册中心registry,监控中心monitor。
前三个是必选的,注册中心和监控中心是可选的。
容器container是为服务提供者的启动提供支持。
在提供者和消费者刚启动时与注册中心交互,服务提供者把自己的服务注册到registry,而消费者告诉注册中心自己需要订阅的服务。
监控中心负责记录服务调用的时间和次数(消费者和提供者定时异步地向monitor发送,monitor负责记录)。

当注册中心和监控中心都挂掉的时候,是否还可以正常运作?
可以的,因为消费者在本地缓存有服务提供的列表,消费者可以和提供者直连。

整体结构,分为10层,从上到下:(Dubbo的工作原理和结构)
service, config, proxy, registry, cluster, monitor, protocol, exchange, transport, serialize
服务层,配置层,代理层, 注册中心层,路由层(封装提供者provider路由和负载均衡),监控中心层,协议层(封装rpc调用),数据交换层(封装请求相应模式),传输层,序列化层

Dubbo中的invoker:就是远程调用的抽象。

Dubbo中的SPI机制?(没有理解,再背一背
SPI(service provider interface),服务提供接口。作用是可以让我们动态地找到服务的实现。

SPI的原理是:我们把服务的实现类写到配置文件中,然后启动spring容器来加载配置文件,使用反射来加载该实现类。我们可以通过修改配置文件来方便和快速更改我们服务所使用的的实现类。

Dubbo没有使用原版的java SPI实现,而对这个做了加强。可以让我们进行扩展。比如实现原接口(如负载均衡的LoadBalance),然后把该实现类写入配置文件即可。

Dubbo的微内核架构?(没有理解,再背一背
微内核架构:是由微内核+插件组成的。

微内核的作用就是组装插件。主要的功能和后续的扩展都由插件完成。

Dubbo使用的是java的SPI,一种简单的Factory管理插件的方式。

Dubbo的负载均衡策略:
什么是负载均衡?
我们现在的服务的并发量通常都比较大,所以会把服务部署到服务器集群上,也就是多台服务器同时运行着同一套代码。这时就会出现一个问题,一个请求来的时候到底哪台服务器应该去处理这个请求呢?
当然是当前时刻服务器压力小的来处理这个请求,所以这中间请求的分配问题就是负载均衡。

Dubbo提供的负载均衡策略有哪些?
1.随机负载均衡(RandomLoadBalance) 【默认采用】
比如现在有两个服务器,分别的权重是7和3。那么把它们当做[0,7]和[7,10]两个区间。然后在整个大区间内生成随机数,这个数落在哪段,哪个服务器就来处理这个请求。
2.最小活跃数负载均衡(LeastActiveLoadBalance)
活跃数(Active)指的是针对处理服务器请求的这个方法,该方法它有自己独立的活跃数。当该方法接到一个对应的请求后活跃数加1,当该方法处理完对应的请求后活跃数减1。当很多请求到来时,每个服务器的请求对应的方法的活跃数都开始上升。但是不同服务器处理请求的速度和效率不同,处理快的其活跃数不会那么的高,所以按照这种方法下次请求会分配给处理快的那个服务器上对应的方法。
如果同时的活跃数都相同时,那就根据权重来进行一次随机负载均衡。(RandomLoadBalance)
3.加权轮训负载均衡(RoundRobinLoadBalance) (不清楚,再背一下)
轮训就是依次把请求分发给服务器。加权轮训就是让更多的请求落在权重更大的服务器上
比如来了10次请求,有两台服务器,权重分别是7和3,那么权重为7的那个服务器承担7次请求,而另外一个承担3次请求。
4.一致性hash负载均衡(ConsistentHashLoadBalance)(不清楚,再背一下)
一致性哈希算法是根据你请求的参数作为缓存结点生成一个hash,并投射在圆环上。然后找第一个大于等于该hash值的服务器结点,则这个请求由这个服务器结点来处理。如果这个结点挂掉,则下次继续往后找服务器结点即可。
在dubbo里进一步引入了虚拟结点,就是一个服务器有多个结点,这样可以使结点分布更加均匀。

Dubbo的序列化协议? (不清楚,再背一下)
Dubbo支持的序列化协议有:jdk自带的,json, 还有跨语言的hessian2和protobuf等,还有专门用于java语言高性能的kyro和FST等。

为什么不用jdk自带的序列化?
1.不支持跨语言
2.序列化后字节数组很大,传输性能差

json性能差,所以不用。

跨语言的就使用hessian2和protobuf。

专门用于java语言的kyro和FST等性能非常好,由于kyro的平均相应时间很短和TPS很高,所以生产环境里可以使用kyro。
TPS(Transaction per sencond)每秒处理事务数目,也即是吞吐量。