ZERO
持续更新 请关注:https://zorkelvll.cn/blogs/zorkelvll/articles/2018/12/28/1546004534620
背景
本文主要是记录在学习 Java - Dubbo 过程中的一些知识点备忘!
一、基本概念
1、Dubbo
Dubbo是一款高性能、轻量级的开源Java RPC框架,具有三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
注意:该dubbo架构图,需要可以自己手写画出来
说明:
- 服务容器负责启动、加载、运行服务提供者
- 服务提供者在启动时,向注册中心注册自己提供的服务
- 服务消费者在启动时,向注册中心订阅自己所需的服务
- 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者
- 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用;如果调用失败,再选另一台调用
- 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心
2、RPC
RPC远程过程调用:是一种通过网络从远程计算机程序上请求服务,且不需要了解底层网络技术的通信机制;也即,RPC是主要是解决远程通信间的问题!
RPC调用流程图(即RPC框架如dubbo解决的是第2~8步)
OR 另一种流程图
注意:该RPC调用流程图,需要可以自己手写画出来
step1:服务消费方client调用,以本地调用方式调用服务
----以下是RPC框架client功能部分封装的
step2:client stub在接收到调用后,负责将方法、参数等组装成能够进行网络传输的消息体(在java中即是序列化过程)
step3:client stub找到服务地址,并将消息发送给服务端
----以下是RPC框架server功能部分封装的
step4:server stub收到消息后进行解码(在java中即是反序列化过程)
step5:server stub根据解码结果调用本地的服务
step6:本地服务执行并将结果返回给server stub
step7:server stub将返回结果打包成消息(在java中即是序列化过程)并发送至消费方
----以下是RPC框架client功能部分封装的
step8:client stub接收到消息,并进行解码(在java中即是反序列化过程)
step9:服务消费方最终得到结果
另外,一个时序图如下
RPC框架:即负责屏蔽掉底层的传输方式(TCP或者UDP)、序列化方式以及通信细节!如阿里的HSF、Dubbo,其核心目标是解决分布式系统中服务之间的调用问题
3、RPC框架技术
3.1 建立通信
在客户端和服务端之间建立TCP连接,远程过程调用的所有交换的数据都是在这个连接里传输
3.2 服务寻址
- 服务注册:将服务注册到服务注册中心,注册中心存储该服务的IP、端口、调用方式(协议、序列化协议)等(ZK,即是在ZK中创建一个znode节点进行信息的存储)
- 服务发现:消费者在第一次调用服务时,会通过注册中心寻找相应服务的IP地址列表并缓存在本地,然后直接通过负载均衡算法从IP地址列表中取一个服务提供者的服务器调用服务
3.3 网络传输
数据传输采用什么协议,数据该如何序列化及反序列化
3.4 NIO通信
大部分RPC框架如Dubbo、HSF、Avro,都是基于Netty这个IO通信框架的(Netty是业界流行的 NIO框架之一,它的健壮性、功能、性能、可定制性和可扩展性在同类框架中都是首屈一指的)
3.5 服务调用
二、Dubbo原理
dubbo共分为10层,其中service和config层为API,其余各层均为SPI(API application programming interface是给使用者用的,SPI service provider interface是给扩展者使用的)
- 第一层:service-接口层,即服务提供者和消费者的实现
- 第二层:config-配置层,主要是对dubbo进行各种配置的
- 第三层:proxy-服务接口透明代理层,生成消费者端Stub和提供者者端Skeleton
- 第四层:registry-服务注册层,负责服务的注册和发现
- 第五层:cluster-集群层,封装多个服务提供者的路由以及负载均衡,将多个实例组合成一个服务
- 第六层:monitor-监控层,对rpc接口的调用次数和调用时间进行监控
- 第七层:protocol-远程调用层,封装rpc调用
- 第八层:exchange-信息交换层,封装请求响应模式,同步转异步
- 第九层:transport-网络传输层,抽象mina和netty为统一接口
- 第十层:serialize-数据序列化层,以支持网络传输(默认hessian2)
三、Dubbo负载均衡
dubbo提供多种负载均衡策略,默认为random随机调用策略
1、 基于权重的随机负载均衡机制 Random LoadBalance(默认)
- 随机,根据权重设置随机概率
- 在一个截面上碰撞的概率很高,但是调用量越大分布越均匀,且按概率使用权重后也比较均匀,有利于动态调整提供者权重
2、基于权重的轮询负载均衡机制 RoundRobin LoadBalance(不推荐)
- 轮询,按公约后的权重设置轮询比率
- 存在慢的提供者累积请求的问题
3、最少活跃调用数 LeastActive LoadBalance
- 最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差
- 使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大
4、一致性Hash ConsistentHash LoadBalance
- 一致性Hash,相同参数的请求总是发到同一提供者(如果需要的不是随机负载均衡,而是要一类请求到一个节点,则应该采用一致性hash策略)
- 当一台提供者挂掉时,原本发往该提供者的请求,基于虚拟节点,会平摊到其他提供者,不会引起剧烈变动
- 一致性hash算法:https://crossoverjie.top/JCSprout/#/algorithm/Consistent-Hash
- 缺省时只对第一个参数hash,若需要修改,可配置
<dubbo:parameter key="hash.arguments" value="0,1" />
- 缺省时用160份虚拟节点,若需要修改,可配置
<dubbo:parameter key="hash.nodes" value="320" />
5、配置方式
- xml配置方式:服务端服务级别(dubbo:service loadbalance)、客户端服务级别(dubbo:reference loadbalance)、服务端方法级别(dubbo:service dubbo:method loadbalance)、客户端方法级别(dubbo:reference dubbo:method loadbalance)
- 注解配置方式:@Service @Reference
四、Dubbo注册中心zk
在实际生产中,如果zk注册中心宕掉,在一段时间内服务消费方还是能够调用提供方的服务的;这是因为实际上它是使用的本地缓存列表中的服务地址列表信息进行调用的,这也是dubbo健壮性的一个方面
dubbo的健壮性
- 监控中心宕掉不影响使用,只是丢失部分采样数据
- 数据库宕掉后,注册中心仍能通过缓存提供服务列表查询,但不能注册新服务
- 注册中心对等集群,任意一台宕掉后,将自动切换到另一台
- 注册中心全部宕掉后,服务提供者和服务消费者仍能通过本地缓存通讯
- 服务提供者无状态,任意一台宕掉后,不影响使用
- 服务提供者全部宕掉后,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复
五、相关问题
Dubbo协议
- 连接个数:单连接
- 连接方式:长连接
- 传输协议:TCP
- 传输方式:NIO异步传输
- 序列化:Hessian
- 适用范围:入传出参数数据包较小(建议小于100K),消费者比提供者个数多,单一消费者无法压满提供者,尽量不要用dubbo协议传输大文件或超大字符串