dubbo面试知识总结

简历上写了dubbo几乎每次都被问了dubbo。。。。

dubbo是一个rpc远程调用的框架,用于分布式的远程调用。核心组件为:运行容器、服务提供者、服务发布者、监视器、注册中心。
dubbo面试知识总结
为什么用dubbo

dubbo为soa架构的分布式项目提供了便利,使表现层调用服务变的非常简单,而且dubbo提供了很多不同的传输协议、不同的负载均衡策略、和调用链监控、完全支持spring这些好处。

dubbo支持不同的协议

  • dubbo协议

  • rmi

  • webservice

  • http

  • redis

如何调用不同的协议dubbo使用spi机制加载配置文件实现

dubbo使用zookeeper或redis作为注册中心

dubbo负载均衡策略:

随机(基于权重)、轮询、一致性hash、最少活跃

spi机制:spi就是通过不同的名字去使用不同协议的实现类,这个机制为dubbo可扩展性提供了极大的便利。spi是将实现类的名字写在MET-INF的services文件夹下,然后通过类加载机制去加载不同的类。dubbo的spi与jdk提供的spi是有区别的。dubbo的spi是自实现的一种spi,文件的配置是以key-value形式的,可以更方便的根据名字获取实现类。

RPC

远程过程调用,就是一种通过网络从远程计算机程序上请求服务,而不需要了解网络技术的协议。就是让A服务调用B服务,这两个服务部署在两台不同的机器上,但是A调用B可以像调用本地服务一样调用

服务方调用以本地的方式调用服务

客户端程序找到服务端地址,讲请求信息和服务端地址封装成消息体,并发给服务端

服务端收到这个消息体后先进行解码,然后根据解码结果调用本地服务

服务端将调用的结果进行封装成一个消息体,返回给客户端

客户端收到消息,服务端得到最终结果

为什么要分布式

从开发角度来说把功能分模块开发起来效率高,从并发角度来说,一个服务部署在一个机器上比多个服务部署在一个机器上可以承受的并发更高

dubbo服务导出源码解析(写的比较简单,也就和面试官能这样吹吹,真要学习建议看官网文档)

服务导出的入口方法是ServiceBean.export()。此方法会调用ServiceConfig.export(),进行真正的服务导出

服务导出要做的几件事:

  • 确定服务参数

  • 确定服务支持协议

  • 构造服务最终url

  • 讲服务url注册到注册中心去

  • 根据不同协议启动不同的server,用来接收和处理请求

确定服务的参数

调用ServiceConfig.export()时,ServiceConfig对象就是一个服务,获取这个服务的参数可以从很多地方获取

@Service注解、dubbo.properties、配置中心、系统环境变量

优先级从高到低:系统环境变量大于配置中心大于Service注解大于dubbo配置文件

确定服务支持协议

协议也可能在多个地方进行了配置

application.properties、dubbo.properties、配置中心、-D系统环境变量配置

构造最终url

有了确定的协议、服务名、服务参数就可以构造URL了

将服务URL注册到注册中心去

根据服务URL启动Server

http协议启动tomcat、jetty

dubbo协议启动Netty

dubbo引入源码解析

spring启动的过程中,就会对@Reference注解标注的属性去赋值

对于ReferenceBean,表示应用想要引入的服务信息,在执行get时会做如下几步

先检查和更新参数,把ReferenceBean里的属性更新为优先级最高的参数值

调用init()去生成代理对象ref,get方法返回这个ref

在生成ref之前,会把消费者引入的服务设置参数添加到一个map中,后面会去这个用这个map的参数去注册中心查找服务

实现一个高性能高可靠的RPC框架需要解决哪些问题?

1.应用都基于微服务化,实现资源调用离不开远程调用

2.一个服务可能有多个实例,你在调用时,要如何获取这些实例的地址呢?— 这时候就需要一个服务注册中心,从服务注册中心获取服务的实例列表,再从中选择一个进行调用。

3.选哪个调用好呢?这时候就需要负载均衡了,于是又得考虑如何实现复杂均衡

4.总不能每次调用时都去注册中心查询实例列表吧,这样效率多低呀,于是又有了缓存,有了缓存,就要考虑缓存的更新问题

5.客户端总不能每次调用完都干等着服务端返回数据吧,于是就要支持异步调用;

6.服务端的接口修改了,老的接口还有人在用,怎么办?总不能让他们都改了吧?这就需要版本控制了;

7.服务端总不能每次接到请求都马上启动一个线程去处理吧?于是就需要线程池;

8.服务端关闭时,还没处理完的请求怎么办?是直接结束呢,还是等全部请求处理完再关闭呢?