服务治理之dubbo核心概念

1. 为什么要做系统拆分?如何进行系统拆分?拆分后不用dubbo可以吗?

为什么要做系统拆分?

  1. 单体应用的弊端
  • 部署成本高:无论是修改一行代码还是10行代码,都要全量替换

  • 改动影响大,风险高:不论是代码改动多少,成本都相同

  • 因成本高、风险高,所以导致部署频率低:无法快速交付客户需求

  1. 微服务架构的特点:
  • 针对特定服务发布,影响小、风险小、成本低

  • 频繁发布版本,快速交付需求

  • 低成本扩容、弹性伸缩、适应云环境

  1. 微服务带来的问题:
  • 分布式系统的复杂性:微服务团队的技术栈水平更高

  • 部署、测试和监控的成本问题

  • 分布式事务和CAP的相关问题

拆分后的好处

  • 每个工程独立的git仓库,避免代码冲突

  • 每个码农维护单独的服务,包括开发、测试、发布

  • 方便技术升级,只要保持接口不变:面向接口编程?

  • 代码量几十万的大中型项目,团队里有几十个人。如果不拆分系统,开发效率极其低下,问题很多。

  • 分布式系统拆分之后,可以大幅度提升复杂系统大型团队的开发效率。

如何进行系统拆分?

  1. 领域驱动模型

  2. 多次拆分

拆分后不用dubbo可以吗?

dubbo 就是一种rpc框架,就是本地进行接口调用,但是dubbo会代理这个调用请求,跟远程机器网络通信,给你处理掉负载均衡、
服务实例上下线自动感知、超时重试等问题。

分布式系统示意图

2. 说一下 dubbo 的工作原理?注册中心挂了可以继续通信吗?说说一次rpc请求的流程?

  • kafka高可用架构原理、es分布式架构原理、redis线程模型原理、dubbo工作原理

  • 系统设计:设计MQ、设计搜索引擎、设计一个缓存、设计rpc框架

dubbo工作原理

第一层:service层:provider和consumer,接口,留给自己实现的

第二层:config层:任何一个框架,都需要提供配置文件,让你进行配置

第三层:proxy层:代理层:无论是consumer还是provider,dubbo都会帮你生成代理,代理之间进行网络通信

第四层:registry层:provider注册自己作为一个服务,consumer就可以到注册中心去寻找自己要调用的服务

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

第六层:monitor层:consumer调用provider,调用了多少次啊?统计信息监控

第七层:protocol层:负责集体的providr和consumer之间调用接口。封装rpc调用

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

第九层:transport层:网络传输层,抽象mina和netty为统一接口

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

工作流程

  1. provider 向注册中心去注册

  2. consumer 从注册中心订阅服务,注册中心会通知 consumer 注册好的服务

  3. consumer 调用 provider

  4. consumer 和 provider 都异步的通知监控中心

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

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

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

image.png
  1. 默认的 dubbo 协议,单一长连接,NIO异步通信,基于 hessian 作为序列化。
  • 适用场景:传输数据量很小(单次请求在100kb以内),但是并发量很大

  • 消费者上百台,每天调用量达上亿次。每个消费者维持一个长连接,长连接基于NIO异步通信。

  1. rmi协议:走 java 二进制序列化,多个短连接,适合消费者和提供者差不多,适用于文件的传输。

  2. hessian 协议:走hessian序列化协议

  3. http协议:json序列化

  4. webservice: SOAP 文本序列化

4. dubbo 负载均衡策略

image.png
  1. random loadbalance 基于权重的随机算法。默认、可设置权重

  2. roundrobin 加权轮询算法。均匀地将流量打到机器上去。调整权重

  3. leastactive 最少活跃调用数算法。自动感知,某个机器性能接收的请求越少

  4. consistanthash 一致性hash算法:相同参数的请求一定分发到一个provider上去,当provider挂掉的时候,会基于虚拟节点均匀分布剩余的流量,抖动不会太大。

5. dubbo 集群容错策略

  1. failover cluster 失败自动切换,自动重试到其他机器。默认。读操作

  2. failfast cluster 一次调用失败就立即失败。写操作

  3. failsafe cluster 出现异常时忽略掉。不重要的接口调用:记录日志

  4. failback cluster 失败了后台自动记录请求,然后定时重发。适合写消息队列

  5. forking cluster 并行调用多个provider,只要一个成功就立即返回

  6. broadcast cluster 逐个调用所有的 provider

6. 动态代理策略

  1. 默认使用 javassist 动态字节码生成,创建代理类

  2. 可以通过 spi 扩展机制配置自己的动态代理策略

7. SPI service provider interface

  1. @SPI("dubbo") : 通过 SPI 机制来听实现类,实现类是通过dubbo作为默认key去配置文件中找到的,配置文件名称与接口全限定名一样。

  2. 如果要动态替换掉默认的实现类,需要使用 @Adaptive 接口。
    在protocol接口中,有两个方法加了 @Adaptive 注解,就是说那两个接口会被代理实现。
    通过这个URL中的参数不同,就可以控制动态使用不同的组件实现类。

  3. dubbo 里面提供了大量类似以上的扩展点。如果要扩展一个东西,只要自己写一个jar,让 consumer 或者是 provider 工程,依赖你的jar,
    在你的jar里指定目录下配置好接口名称对应的文件,里面通过key=实现类。

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

服务治理

  1. 调用链路自动生成:

将各个服务之间的调用自动记录下来,然后自动将各个服务之间的依赖关系和调用链路生成出来,做成一张图,显示出来。

  1. 服务访问压力以及时长统计:
  • 需要自动统计各个接口和服务之间的调用次数以及访问延时,分为两个级别:

  • 接口粒度:每个服务的每个接口每天被调用多少次。TP50,TP90,TP99,三个档次的请求延时分别是多少?

  • 从源头入口开始,一个完整的请求链路经过几十个服务之后,完成一次请求,每天全链路走多少次,全链路请求延时的 TP50,TP90,TP99 分别是多少?

  1. 其他的
  • 服务分层(避免循环依赖)

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

  • 服务鉴权

  • 每个服务的可用性的监控(接口调用成功率?几个9?)

服务降级

      

mock:服务接口实现类

失败重试和超时重试

  • 如果超时了, timeout 就会设置超时时间。200ms

  • 如果是调用失败了就会重试指定的次数

  • retries = 3 。读请求,如果第一次没读到,报错。重试指定的次数,尝试再读取两次。

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

image.png
  1. 每个请求必须有唯一的标识:订单ID

  2. 每次处理完请求之后,必须有一个记录标识这个请求处理过了:用mysql中记录个状态,支付之前记录一条这个订单的支付流水。

  3. 每次接收请求需要进行判断之前是否处理过的逻辑处理。
    如果有一个订单已经支付了,就已经有了一条支付流水,那么如果重复发送这个请求,则此时先插入支付流水,order已经存在了,
    唯一键约束生效,报错插不进去的。

  4. redis 支付订单之前,先插入一条支付流水,order_id 建一个唯一键。重复请求过来时,先查下 order_id 是否有值,有就不需要再重复了。

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

  1. 用 dubbo 的一致性 hash 负载均衡策略,将某一个订单 ID 对应的请求都分发到某个机器上去,接着就是在那个机器上因为
    可能还是多线程并发执行的,得立即将某个订单对应的请求扔到一个内存队列中,强制排队,来保证顺序性。
  • 造成的问题:机器热点
  1. 合并多个操作为一个操作。

11. 如何自己设计一个类似 dubbo 的 rpc 框架?

  1. 注册中心

  2. 消费者需要到注册中心拿到对应的服务信息

  3. 发请求,基于动态代理:面向接口获取一个动态代理,这个动态代理就是接口在本地的一个代理,然后这个代理会找到服务对应的机器地址

  4. 发送到哪个服务上去?负载均衡

  5. 找到一台机器,怎么发送? netty、nio方式。发送啥格式数据? hessian 序列化协议

  6. 服务器端需要针对你自己的服务生成一个动态代理,监听某个网络端口了,然后代理你本地的服务代码。接收到请求时,就调用对应的服务代码。

12. dubbo 底层架构原理

13. dubbo 底层的网络通信机制原理

14. dubbo 框架从架构设计角度,是怎么保证极高的可扩展性的?

  1. 核心的组件全部接口化,组件和组件之间的调用,必须是依托于接口,去动态找配置的实现类,如果没有配置就用它自己默认的。

  2. 提供一种自己实现的组件的配置方式。比如自己实现了某个组件,配置一下,人家到时候运行时直接找配置的组件。

15. 设计一个 rpc 框架,网络通信、代理机制、负载均衡等该如何设计?

  1. 动态代理:rpc 框架的一切的逻辑细节,都是在这个动态代理中实现的,动态代理里面的代码逻辑是 rpc 框架核心的逻辑。

  2. 服务注册中心,使用什么技术实现?

  • 手写。类似于map的数据结构。服务去注册,其他服务去拉取注册表进行发现。

  • zookeeper:服务注册表的数据结构

  1. cluster层,从本地缓存的服务注册列表里获取到要调用的服务机器列表

  2. 负载均衡:注册的服务列表中选择一个机器返回

  3. 数据组织:协议、序列化(复杂的请求数据序列化为二进制数组)机制。底层用什么网络通信框架(netty、mina)

参考代码
https://github.com/ElegantResearcher/learn/tree/master/rpc

参考文献

https://gitee.com/shishan100/Java-Interview-Advanced

你可能感兴趣的:(服务治理之dubbo核心概念)