分布式RPC框架

dubbo常见问题:

1. 问dubbo的工作原理:服务注册,注册中心,服务生产者,消费者,代理通信,负载均衡

2. 问网络通信,序列化: dubbo协议,长连接,NIO,hessian序列化协议

3. 问负载均衡策略,集群容错策略,动态策略:dubbo跑起来后一些功能是如何运转,怎么做复制均衡,怎么做容错,怎么生成动态代理?

4. 问dubbo SPI机制:是否了解SPI机制?如何基于SPI机制对dubbo进行扩展?

5. dubbo服务治理,超时,降级,重试等。

1. 为什么要进行系统拆分?

项目大了,代码多了,很多代码冲突,代码合并维护困难。改一个地方,回归测试工作量很大。

大项目发布上线依赖很多外部东西,发布特别麻烦。

2. 如何进行拆分?

系统拆分需要经过多轮拆分,不可能一次就拆分好了。考虑多少个人维护多少个服务。

3.拆分后为什么要用Dubbo, 不用Dubbo可以吗?DubboThrift有什么区别?

可以不用。可以用纯基于Spring MVC,纯http接口相互通信,但是维护成本很高。

Dubbo已经在RPC做得很好了,成熟的RPC框架,本地就是进行接口调用,Dubbo代理调用请求,跟远程网络通信,处理负载均衡,超时重试等等功能。

4. 说一下的Dubbo 的工作原理?注册中心挂了可以继续通信吗?说说发起一次RPC请求的流程?

4.1. dubbo工作原理

第一层: service层/接口层: provider和consumer接口,留给你来实现服务的生产者和消费者

第二层:config层:提供配置文件,对dubbo进行各种配置

第三层:proxy层:dubbo为provider和consumer生成代理,代理之间进行网络通信

第四层:registry层:负责服务的注册与发现

第五层:cluster层:provider可以部署在多台机器,组成集群

第六层:monitor层:对RPC接口调用次数和调用时间进行监控

第七层:protocol层:远程调用层,封装RPC调用

第八层:exchange层:进行信息交换,封装请求响应,同步转异步

第九层:transport层:网络传输

第十层:serialize层:数据序列化

工作流程:

第一步:provider 向注册中心去注册

第二步:consumer 从注册中心订阅服务,注册中心会通知 consumer 注册好的服务

第三步:consumer 调用 provider

第四步:consumer 和 provider 都异步通知监控中心

  4.2. 注册中心挂了可以继续通信吗?

可以。刚开始初始化的时候,消费者会将生产者的地址信息拉取到本地缓存,所以注册中心挂了可以继续通信。

5. dubbo支持哪些通信协议?支持哪些序列化协议?

1. dubbo支持不同的通信协议

1). dubbo协议

dubbo://192.168.0.1:20188

默认dubbo协议,单一长连接,NIO异步通信,Hessian二进制序列化。

适用场景:传输数据量小(每次请求100KB内),消费者比提供者个数多, 适合于小数据量大并发的服务调用。

  • 为什么要消费者比提供者个数多?

假设网络为千兆网卡(1024Mbit=128MByte),根据网络测试,每条连接最多只能压满7MByte,理论上1个服务提供者需要20个消费者才能压满网卡。

  • 为什么不能传大包?

假设网络为千兆网卡(1024Mbit=128MByte),每条连接最大7Mbyte,如果请求是大包(比如500KByte),

则单个服务提供者的TPS最大:128Mbyte / 500KByte = 262。
           单个消费者调用单个服务提供者TPS最大:7MByte / 500KByte = 14。
           所有单个请求包越大,消费者调用的TPS越低,网络成为瓶颈。

  • 为什么异步单一长连接?

大多数网络都是服务提供者少,消费者请求者多。通过单一连接,保证单一消费者不会压垮提供者,长连接可以减少握手次数,使用异步IO,复用线程池。

2)  Hessian协议。用于集成Hessian的服务,Hessian底层采用Http通讯,采用Servlet暴露服务。

适用范围:传入传出参数数据包较大,提供者比消费者个数多,提供者压力较大,可传文件。适用场景:页面传输,文件传输,或与原生hessian服务互操作.

因此比较高效的做法是带上传下载文件的服务使用hessian协议,普通的服务使用dubbo协议。

其他协议, 如rmi协议(java序列化),http协议(JSON序列化),webservice(SOAP序列化)

为什么PB(protocol  buffer)效率最高?

         PB是google出品的轻量高效的结构化数据存储格式,性能比JSON,XML要高很多。

性能高原因:1. 使用proto编译器,自动序列化和反序列化,速度非常快。2.数据压缩效果好,序列化后数据体积小,传输带宽和速度有优势。

  

6. dubbo 负载均衡策略和集群容错策略都有哪些?动态代理策略呢?

  6.1 负载均衡策略:

1. Random loadbalance

dubbo默认是random load balance,随机负载均衡。可以对provider设置不同权重,按照权重来做负载均衡,权重越大分配到流量越高。

2. LeastActive loadbalance

自动感知,如果某机器性能越差,接收请求越少,越不活跃,就会给更少的请求。

3. Consistent hash loadbalance

一致性hash算法,相同参数请求分发到一个provider上,这个provider挂了的时候,会基于虚拟节点均匀分配剩余流量,减小抖动。

如果你需要是要某一类请求都到在某一个节点处理,那就选这个一致性 Hash 策略。

   6.2 集群容错策略:

failover cluster模式(默认):

如果某台机器宕机,请求失败几次后重试其他机器。

failfast cluster模式:

一次调用失败就立即失败。比如新增一条记录。

failsafe cluster模式:

出现异常忽略,适用于不重要的接口调用,比如记录日志。

failback cluster模式:

失败后记录请求,然后定时重发,适合于写消息队列。

forking cluster模式:

并行调用多个provider,只要一个成功就立即返回。适用于实时性比较要求比较高的读操作,但会浪费资源。通过forks=”2”来设置最大并行数。

    6.3 动态代理策略:

默认使用 javassist 动态字节码生成,创建代理类。但是可以通过 spi 扩展机制配置自己的动态代理策略。

7. SPI是什么?DubboSPI是什么?

SPI: Service Provider Interface。

比如有个接口A,有3个实现类,实现类A1/A2/A3。那么在系统运行时候对这个接口到底选择哪个实现类?

需要根据指定的配置,去找对应的实现类加载,用这个实现类实例对象。这个就是SPI。

比如通过jar包方式给某个接口提供实现,在自己jar包的META-INF/services/,放一个和接口同名的文件a,里面指定接口的实现就是jar包里某个类。

在调用时,通过jar的a文件找到这个接口应该用哪个实现类。

SPI 机制适用场景?

       适用插件扩展的场景,比如说你开发了一个给别人使用的开源框架,如果你想让别人自己写个插件,插到你的开源框架里面,从而扩展某个功能。

比如jdbc, java提供jdbc接口,没有提供实现类。实际根据具体适用的数据库,比如mysql的jar包,mysql-jdbc-connector.jar引入。

系统运行时,遇到jdbc接口,会在底层适用引入的jar提供的实现类。

dubbo的SPI思想:

Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();

Protocol 接口,在系统运行的时候,dubbo 会判断一下应该选用这个 Protocol 接口的哪个实现类来实例化对象来使用。

@SPI("dubbo")
public interface Protocol {
int getDefaultPort();
@Adaptive
<T> Exporter<T> export(Invoker<T> invoker) throws RpcException;
@Adaptive
<T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;
void destroy();
}

在 dubbo 自己的 jar 里,在/META_INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol文件中:

dubbo=com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol
http=com.alibaba.dubbo.rpc.protocol.http.HttpProtocol
hessian=com.alibaba.dubbo.rpc.protocol.hessian.HessianProtocol

  如何自己扩展 dubbo 中的组件:

自己写个工程,要是那种可以打成 jar 包的,里面的 src/main/resources 目录下,搞一个 META-INF/services,

里面放个文件叫:com.alibaba.dubbo.rpc.Protocol,文件里搞一个my=com.bingo.MyProtocol。自己把 jar 弄到 nexus 私服里去。

然后自己搞一个 dubbo provider 工程,在这个工程里面依赖你自己搞的那个 jar,然后在 spring 配置文件里给个配置:

<dubbo:protocol name=”my” port=”20000” />

provider 启动的时候,就会加载到我们 jar 包里的my=com.bingo.MyProtocol 这行配置里,接着会根据你的配置使用你定义好的 MyProtocol 了,这个就是简单说明一下,你通过上述方式,可以替换掉大量的 dubbo 内部的组件,就是用你自己的 jar 包,然后配置一下即可。

8. 如何基于dubbo进行服务治理、服务降级、失败重试及超时重试?

  服务治理

1. 调用链路自动生成

基于dubbo做分布式系统中,对各个服务之间的调用自动记录下,然后自动将各个服务之间的依赖关系和调用链路生成出来。

服务分层,避免循环依赖。

调用链路失败监控和报警。

2. 服务访问压力以及时长统计

自动统计各个接口和服务之间的调用次数以及访问延时。后面才能看当前系统的压力在哪里,如何来扩容和优化。

3. 服务调用权限和可用性

只有某个服务有权利调用另外一个服务。

可用性监控,接口调用成功率,几个9? 99%, 99.9%,99.99%

  服务降级

服务A调用服务B , B挂了,服务A尝试几次都不行,就要服务降级,走备选逻辑,给用户返回响应。

我们调用接口失败的时候,直接通过mock统一返回null。

也可以设置mock=true,可以通过走mock Service进行降级逻辑处理。

  失败重试和超时重试

失败重试,就是 consumer 调用 provider 要是失败了,比如抛异常了,此时应该是可以重试的,或者调用超时了也可以重试。配置如下:

<dubbo:reference id="xxxx" interface="xx" check="true" async="false" retries="3" timeout="2000"/>

retries:失败重试次数

timeout:超过xxx秒超时返回

9. 分布式服务接口的幂等性如何设计(比如不能重复扣款)?

幂等性:同一个接口,多次发起同一个请求,保证接口结果正确,不能重复操作,多扣款或多插入数据等等。

单机:JVM内存用map或set保存orderid, 记录订单已经支付过。

分布式: 1. 设计一个标识来表示这个请求已经处理过。比如支付之前插入一条记录标识这个订单的支付流水。

重发请求,由于已经插入过这个orderid的流水,唯一键约束,插不进去。

2. 数据库里记录一个支付状态。比如未支付,已支付等等。

3. 利用Redis来保存一个是否处理过的标识。SETNX key。

PS:没有通用解决方案,需要结合业务来保证幂等性。

10. 分布式服务接口请求的顺序性如何保证?

解决方案:

1. 业务逻辑上的设计,最好不要设计这种需要保证顺序性的。

一旦引入,比如使用分布式锁(很重),会导致系统复杂度上升,效率降低,热点数据压力过大等问题。

2. 使用dubbo的一致性hash负载均衡策略。

将某个请求(某个订单id)对应的请求都要分发到同一个机器上,然后将对应的多个请求放入一个内存队列,强制排队,这样来保证顺序。

11. 如何自己设计一个类似 Dubbo RPC 框架?

考察点:有没有对某个RPC框架原理有深入理解。能不能从整体上来考虑,考察系统设计能力。

回答思路:

整体包括哪些模块:注册中心,消费者,生产者和想对应的接口,动态代理,负载均衡,底层网络通信协议,序列化协议。RPC框架扩展-SPI机制,超时,降级。

1. 设计注册中心。 保留各个服务的信息,可以用ZK。

2. 服务在注册中心注册,自动生成服务代理,动态代理,自动监听网络请求,

消费者的代理,调用别的服务,实现负载均衡算法,在部署服务的多台机器上,按负载均衡算法挑选服务,建立网络连接,发送网络请求。

3. 网球请求怎么发?可以用netty,NIO等等。

4.  请求中数据格式?序列化协议。可以用hessian序列化,或者别的,pb等等,通过字节流发送到服务端。

5. 服务接收端要反序列化,反序列化为对象,在本地调用服务接口,处理完结果后序列化返回给消费者。

6. RPC框架怎么扩展: SPI机制。

7.  怎么做超时,降级。

参考资料:

《互联网Java进阶面试训练营》的笔记 -- 中华石杉

[Java复习] 分布式PRC - Dubbo的更多相关文章

  1. [Java复习] 分布式锁 Zookeeper Redis

    一般实现分布式锁都有哪些方式? 使用 Redis 如何设计分布式锁?使用 Zookeeper 来设计分布式锁可以吗? 这两种分布式锁的实现方式哪种效率比较高? 1. Zookeeper 都有哪些使用场 ...

  2. [Java复习] 分布式事务 Part 2

    分布式事务了解吗?如果解决分布式事务问题的? 面试官心里: 只要聊到你做了分布式系统,必问分布式事务,起码得知道有哪些方案,一般怎么来做,每个方案的优缺点是什么. 为什么要有分布式事务? 分布式事务实 ...

  3. [Java复习] 分布式高可用-Hystrix

    什么是Hystrix? Hystrix 可以让我们在分布式系统中对服务间的调用进行控制,加入一些调用延迟或者依赖故障的容错机制. Hystrix 的设计原则 对依赖服务调用时出现的调用延迟和调用失败进 ...

  4. [Java复习] 分布式事务 Part 1

    1. CAP理论 C: Consistency 一致性 A: Availability 可用性 P: Partition tolerance 分区容错性 CAP定理:一个分布式系统不可能同时满足CAP ...

  5. Jmeter分布式测试dubbo接口2

    上次我们将dubbo接口与jmeter集成起来,但是jmeter是由java实现的,本身有很多限制,无法实现高并发,我们需要借助分布式来实现大压力测试. 在上次的例子中,我们只是实现了简单的dubbo ...

  6. java 复习003 之排序篇

    由java 复习003跳转过来的C语言实现版见some-sort-algorithms 快速排序(不稳定 O(n log n)) package vell.bibi.sort_algorithms; ...

  7. java 复习001

    java 复习001 比较随意的记录下我的java复习笔记 ArrayList 内存扩展方法 分配一片更大的内存空间,复制原有的数据到新的内存中,让引用指向新的内存地址 ArrayList在内存不够时 ...

  8. 分布式架构--Dubbo项目实战学习文档

    安装Dubbo注册中心(Zookeeper-3.4.6) 安装Dubbo管理控制台 Tomcat中部署web应用 ---- Dubbo服务消费者Web应用war包的部署 Dubbo监控中心的介绍与简易 ...

  9. java复习(1)---java与C++区别

    [系列说明]java复习系列适宜有过java学习或C++基础或了解java初步知识的人阅读,目的是为了帮助学习过java但是好久没用已经遗忘了的童鞋快速捡起来.或者教给想快速学习java的童鞋如何应用 ...

随机推荐

  1. linux复制、压缩打包、解压缩等操作

    1. 复制:cp命令,可复制一个文件夹下的所有文件和子目录.子文件,但是不包括本目录名,例如:不想包含目录名python3.7,想包含的是该目录下的所有子文件和子目录 cp -r /usr/local ...

  2. SVN安装配置教程

    第一步:安装Apache LInux centos6.5 ​ (备注:为了方便可以把linux防火墙关掉,这样就不需要一个一个开端口了,建议开发测试可以这样,正式环境不推荐) ​ 第二步:安装SVN服 ...

  3. python访问aws-S3服务

    创建本地 AWS 凭证文件 登录 AWS 管理控制台 并通过以下网址打开 IAM 控制台 https://console.amazonaws.cn/iam/. 创建一个新用户,其权限仅限于您希望您的代 ...

  4. 13 复习 - webpack基本配置2

    在webpack下使用样式表 1.安装处理样式表的loader cnpm i style-loader css-loader -D //css cnpm i less-loader less -D / ...

  5. Tomcat 配置及优化

    Tomcat配置优化,主要在于优化tomcat运行模式,并发参数和线程数, 以及jvm堆内存和垃圾回收相关参数的优化.下面将逐一介绍. 1. tomcat的3种运行模式 1.1 BIO - 同步阻塞I ...

  6. windows下递归删除指定文件和文件夹

    //删除文件del *.后缀 /s//删除文件夹for /r 目录 %a in (文件夹名\) do @if exist "%a" rd /s/q "%a"

  7. 25 | MySQL是怎么保证高可用的?

    在上一篇文章中,我和你介绍了binlog的基本内容,在一个主备关系中,每个备库接收主库的binlog并执行. 正常情况下,只要主库执行更新生成的所有binlog,都可以传到备库并被正确地执行,备库就能 ...

  8. java上传超大文件

    上周遇到这样一个问题,客户上传高清视频(1G以上)的时候上传失败. 一开始以为是session过期或者文件大小受系统限制,导致的错误.查看了系统的配置文件没有看到文件大小限制,web.xml中sees ...

  9. 【luoguP4777】【模板】扩展中国剩余定理(EXCRT)

    (扩展)中国剩余定理 对于一组同余方程 \(x\equiv a_1(mod \quad n_1)\) \(x\equiv a_2(mod \quad n_2)\) \(x\equiv a_3(mod ...

  10. python 根据时间戳获取秒🐱

    print("当前时间: ",time.strftime('%Y.%m.%d %H:%M:%S ',time.localtime(time.time()))) import tim ...