美文网首页
服务治理之dubbo核心概念

服务治理之dubbo核心概念

作者: 南园故剑00 | 来源:发表于2020-06-01 17:53 被阅读0次

    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?)

    服务降级

        <dubbo:reference id="appServer" interface="com.gupaoedu.dubbo.IAppInterface" version="1.0.0"
                         cluster="failover"
                         timeout="10"
                         mock="com.DataBaseConnection.dubbo.TestMock"
                         retries="3"/>  
    

    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核心概念

          本文链接:https://www.haomeiwen.com/subject/uhmszhtx.html