这是面试专题系列第四篇,Dubbo系列。Dubbo本身并不复杂,而且官方文档写的非常清楚详细,面试中dubbo的问题一般不会很多,从分层到工作原理、负载均衡策略、容错机制、SPI机制基本就差不多了,最大的一道大题一般就是怎么设计一个RPC框架了,但是如果你工作原理分层都搞明白了这个问题其实也就相当于回答了不是吗。

说说Dubbo的分层?

从大的范围来说,dubbo分为三层,business业务逻辑层由我们自己来提供接口和实现还有一些配置信息,RPC层就是真正的RPC调用的核心层,封装整个RPC的调用过程、负载均衡、集群容错、代理,remoting则是对网络传输协议和数据转换的封装。

划分到更细的层面,就是图中的10层模式,整个分层依赖由上至下,除开business业务逻辑之外,其他的几层都是SPI机制。

能说下Dubbo的工作原理吗?

  1. 服务启动的时候,provider和consumer根据配置信息,连接到注册中心register,分别向注册中心注册和订阅服务

  2. register根据服务订阅关系,返回provider信息到consumer,同时consumer会把provider信息缓存到本地。如果信息有变更,consumer会收到来自register的推送

  3. consumer生成代理对象,同时根据负载均衡策略,选择一台provider,同时定时向monitor记录接口的调用次数和时间信息

  4. 拿到代理对象之后,consumer通过代理对象发起接口调用

  5. provider收到请求后对数据进行反序列化,然后通过代理调用具体的接口实现

为什么要通过代理对象通信?

主要是为了实现接口的透明代理,封装调用细节,让用户可以像调用本地方法一样调用远程方法,同时还可以通过代理实现一些其他的策略,比如:

1、调用的负载均衡策略

2、调用失败、超时、降级和容错机制

3、做一些过滤操作,比如加入缓存、mock数据

4、接口调用数据统计

说说服务暴露的流程?

  1. 在容器启动的时候,通过ServiceConfig解析标签,创建dubbo标签解析器来解析dubbo的标签,容器创建完成之后,触发ContextRefreshEvent事件回调开始暴露服务
  2. 通过ProxyFactory获取到invoker,invoker包含了需要执行的方法的对象信息和具体的URL地址
  3. 再通过DubboProtocol的实现把包装后的invoker转换成exporter,然后启动服务器server,监听端口
  4. 最后RegistryProtocol保存URL地址和invoker的映射关系,同时注册到服务中心

说说服务引用的流程?

服务暴露之后,客户端就要引用服务,然后才是调用的过程。

  1. 首先客户端根据配置文件信息从注册中心订阅服务

  2. 之后DubboProtocol根据订阅的得到provider地址和接口信息连接到服务端server,开启客户端client,然后创建invoker

  3. invoker创建完成之后,通过invoker为服务接口生成代理对象,这个代理对象用于远程调用provider,服务的引用就完成了

有哪些负载均衡策略?

  1. 加权随机:假设我们有一组服务器 servers = [A, B, C],他们对应的权重为 weights = [5, 3, 2],权重总和为10。现在把这些权重值平铺在一维坐标值上,[0, 5) 区间属于服务器 A,[5, 8) 区间属于服务器 B,[8, 10) 区间属于服务器 C。接下来通过随机数生成器生成一个范围在 [0, 10) 之间的随机数,然后计算这个随机数会落到哪个区间上就可以了。

  2. 最小活跃数:每个服务提供者对应一个活跃数 active,初始情况下,所有服务提供者活跃数均为0。每收到一个请求,活跃数加1,完成请求后则将活跃数减1。在服务运行一段时间后,性能好的服务提供者处理请求的速度更快,因此活跃数下降的也越快,此时这样的服务提供者能够优先获取到新的服务请求。

  3. 一致性hash:通过hash算法,把provider的invoke和随机节点生成hash,并将这个 hash 投射到 [0, 2^32 - 1] 的圆环上,查询的时候根据key进行md5然后进行hash,得到第一个节点的值大于等于当前hash的invoker。

图片来自dubbo官方

  1. 加权轮询:比如服务器 A、B、C 权重比为 5:2:1,那么在8次请求中,服务器 A 将收到其中的5次请求,服务器 B 会收到其中的2次请求,服务器 C 则收到其中的1次请求。

集群容错方式有哪些?

  1. Failover Cluster失败自动切换:dubbo的默认容错方案,当调用失败时自动切换到其他可用的节点,具体的重试次数和间隔时间可用通过引用服务的时候配置,默认重试次数为1也就是只调用一次。

  2. Failback Cluster快速失败:在调用失败,记录日志和调用信息,然后返回空结果给consumer,并且通过定时任务每隔5秒对失败的调用进行重试

  3. Failfast Cluster失败自动恢复:只会调用一次,失败后立刻抛出异常

  4. Failsafe Cluster失败安全:调用出现异常,记录日志不抛出,返回空结果

  5. Forking Cluster并行调用多个服务提供者:通过线程池创建多个线程,并发调用多个provider,结果保存到阻塞队列,只要有一个provider成功返回了结果,就会立刻返回结果

  6. Broadcast Cluster广播模式:逐个调用每个provider,如果其中一台报错,在循环调用结束后,抛出异常。

了解Dubbo SPI机制吗?

SPI 全称为 Service Provider Interface,是一种服务发现机制,本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类,这样可以在运行时,动态为接口替换实现类。

Dubbo也正是通过SPI机制实现了众多的扩展功能,而且dubbo没有使用java原生的SPI机制,而是对齐进行了增强和改进。

SPI在dubbo应用很多,包括协议扩展、集群扩展、路由扩展、序列化扩展等等。

使用方式可以在META-INF/dubbo目录下配置:

key=com.xxx.value

然后通过dubbo的ExtensionLoader按照指定的key加载对应的实现类,这样做的好处就是可以按需加载,性能上得到优化。

如果让你实现一个RPC框架怎么设计?

  1. 首先需要一个服务注册中心,这样consumer和provider才能去注册和订阅服务
  2. 需要负载均衡的机制来决定consumer如何调用客户端,这其中还当然要包含容错和重试的机制
  3. 需要通信协议和工具框架,比如通过http或者rmi的协议通信,然后再根据协议选择使用什么框架和工具来进行通信,当然,数据的传输序列化要考虑
  4. 除了基本的要素之外,像一些监控、配置管理页面、日志是额外的优化考虑因素。

那么,本质上,只要熟悉一两个RPC框架,就很容易想明白我们自己要怎么实现一个RPC框架。

- END -

《我想进大厂》之Dubbo普普通通9问的更多相关文章

  1. 《我想进大厂》之mysql夺命连环13问

    想进大厂,mysql不会那可不行,来接受mysql面试挑战吧,看看你能坚持到哪里? 1. 能说下myisam 和 innodb的区别吗? myisam引擎是5.1版本之前的默认引擎,支持全文检索.压缩 ...

  2. 想进大厂?字节跳动等独角兽公司都在招募Python工程师!(Python就是第一语言)

    在本文章中,作者通过自身经历,力求客观的谈谈个人选择学习Python的动机,以及独角兽公司对Python工程师的要求及薪资. 从目前各种迹象(企业招聘,语言排名等)看来Python相对Java应该是暂 ...

  3. 《我想进大厂》之Spring夺命连环10问

    1.说说Spring 里用到了哪些设计模式? 单例模式:Spring 中的 Bean 默认情况下都是单例的.无需多说. 工厂模式:工厂模式主要是通过 BeanFactory 和 Application ...

  4. 想进大厂,想收获高薪offer,资深猎头告诉你怎么做......

    其实吧,面试官面试的时候主要就看三个方面:现在能力如何,未来潜力如何,人品如何. 第一个因素是最重要的,因为后面两个因素有太多的人为判断因素,无法量化.所谓的面试准备,"现在能力如何&quo ...

  5. 《我想进大厂》之Redis夺命连环11问

    这是面试题系列第三篇--redis专题. 说说Redis基本数据类型有哪些吧 字符串:redis没有直接使用C语言传统的字符串表示,而是自己实现的叫做简单动态字符串SDS的抽象类型.C语言的字符串不记 ...

  6. 《我想进大厂》之JVM夺命连环10问

    这是面试专题系列第五篇JVM篇. 说说JVM的内存布局? Java虚拟机主要包含几个区域: 堆:堆Java虚拟机中最大的一块内存,是线程共享的内存区域,基本上所有的对象实例数组都是在堆上分配空间.堆区 ...

  7. 《我想进大厂》之Java基础夺命连环16问

    说好了面试系列已经完结了,结果发现还是真香,嗯,以为我发现我的Java基础都没写,所以这个就算作续集了,续集第一篇请各位收好. 说说进程和线程的区别? 进程是程序的一次执行,是系统进行资源分配和调度的 ...

  8. 《我想进大厂》之Zookeeper夺命连环9问

    谈谈你对Zookeeper的理解? Zookeeper是一个开源的分布式协调服务,由雅虎公司创建,由于最初雅虎公司的内部研究小组的项目大多以动物的名字命名,所以后来就以Zookeeper(动物管理员) ...

  9. 想进大厂嘛?这里有一份通关秘籍:iOS大厂面试宝典

    1.NSArray与NSSet的区别? NSArray内存中存储地址连续,而NSSet不连续 NSSet效率高,内部使用hash查找:NSArray查找需要遍历 NSSet通过anyObject访问元 ...

随机推荐

  1. Dos拒绝服务Syn-Flood泛洪攻击--Smurf 攻击(一)

    Dos拒绝服务利用程序漏洞或一对一资源耗尽的Denial of Service 拒绝服务DDos 分布式拒绝服务 多对一 Syn-Flood泛洪攻击 发送syn包欺骗服务器建立半连接 攻击代码,利用s ...

  2. Python中的相对路径的表示方法

    2020/6/3 举例: 现在 6-2.py 想使用 /data/lastfm-2k/user_artists.dat 因为 6-2.py 和 data 是同一级目录,所以正确的写法应该是:

  3. HTTP协议(二)---请求和响应

    HTTP通过请求和响应的交换达成通信. HTTP请求 请求报文由请求行(请求方法.请求URI.协议版本).请求首部字段以及内容实体(可能没有)构成. 下面是一个GET请求,没有内容实体: 下面是 一个 ...

  4. Java内部类使用场景和作用

    一.Java内部类的分类 Java内部类一般包括四种:成员内部类.局部内部类.匿名内部类和静态内部类 大多数业务需求,不使用内部类都可以解决,那为什么Java还要设计内部类呢. 二.内部类的使用场景 ...

  5. archaius(1) 概述

    archaius作为配置管理工具,内部主要定义了下几个模块: 配置源 配置源的主要功能是将配置从目标位置加载到内存中.详见:archaius源码分析之配置源 配置管理器 配置管理器的主要功能是管理内存 ...

  6. Flutter学习五之网络请求和轮播图的实现

    上期讲到了,怎样实现一个下拉刷新和加载更多的列表,数据更新,需要使用到网络请求,在flutter中,怎样实现一个网络请求呢?官方使用的是dart io中的HttpClient发起的请求,但HttpCl ...

  7. 搞 Java 的年薪 40W 是什么水平?

    文章首发于[陈树义的博客],点击跳转到原文https://www.cnblogs.com/chanshuyi/p/how_to_earn_400_thousand_per_year.html 我 20 ...

  8. 一个提高N倍系统新能的编程点,却总是被普通开发们遗忘

    位运算这个概念并不陌生,大多数程序员在进入这个领域的时候或多或少都接触过位运算,估计当时都写过不少练习题的. 位运算本身不难,困难的是大家没有学会在系统设计时用上它,提高系统性能,增加你的不可替代性. ...

  9. Powershell编程基础-004-for语句的使用

    For循环在PowerShell中也称为For语句. 同其他编程语言类似 当指定条件的值为True时,此循环以代码块的形式执行语句,另,For后面接(;;)代表恒为真! 实例1:用于执行指定次数的语句 ...

  10. Java Web学习(四)http协议

    文章更新时间:2020/07/24 一.概念 定义 HTTP:超文本传输协议,是TCP/IP协议的一个应用层协议,用于定义WEB浏览器与WEB服务器之间交换数据的过程. HTTP协议:用于定义客户端与 ...