Dubbo(架构/SPI机制/底层原理)
2021-02-26 09:33:44 2 举报
AI智能生成
Dubbo(架构/SPI机制/底层原理)
作者其他创作
大纲/内容
背景
RPC远程方法调用
RPC是一个远程方法调用的计算机通信协议
底层技术:Socket、Netty、Http、TCP、WebService
Dubbo协议:tcp协议+hessian二进制传输(暴露端口号和IP地址就可以访问)
传统RPC调用的缺点
缺少服务治理,当服务比较多的情况下,URL地址管理起来很复杂
dubbo作为分布式服务治理框架,通过注册中心解决服务治理问题
注册中心
ZooKeeper(官方推荐)
Redis、Multicast、Simple
dubbo的优缺点
面向接口代理的高性能的RPC调用、智能负载均衡及容错机制、服务自动注册与发现、高度可扩展、可视化的服务治理与运维
只支持Java语言
架构原理
角色
Provider:暴露服务的服务提供方(生产者)
Consumer:调用远程服务的服务消费方(消费者)
Registry:服务注册与发现的注册中心
Monitor:统计服务的调用次数和调用时间的监控中心
0. 服务容器负启动,加载运行服务提供者
1. 服务提供者在启动时,向注册中心注册自己提供的服务
2. 服务消费者在启动时,向注册中心订阅自己所需的服务
3. 注册中心返回服务提供者地址列表给消费者,如果有变更
注册中心将基于长连接推送数据给消费者(异步通知)
注册中心将基于长连接推送数据给消费者(异步通知)
4. 服务消费者从提供者地址列表中基于软负载均衡算法,选
一台提供者进行调用,如果调用失败,再选另一台调用
一台提供者进行调用,如果调用失败,再选另一台调用
5. 服务消费者和提供者,在内存中累计调用次数和调用时间
定时每分钟发送一次统计数监控中心
定时每分钟发送一次统计数监控中心
调用过程
消费者
通过配置获取Proxy层动态代理对象
通过Cluster层做负载均衡,选择出一台机器
通过Protocol层选择一种协议来组织请求
通过Exchange层进行请求的封装
通过网络通信框架netty把请求序列化后发出去
提供者
监听端口号,获取请求,将请求反序列化
通过Exchange解析请求
通过Protocol选择协议来解析请求
通过动态代理对象调用具体的实现逻辑
SPI
概念
Service Provider Interface,是一种服务发现机制
基于SPI,我们可以很容易的对Dubbo进行扩展
Dubbo并未使用Java原生的SPI机制,而是对其进行了增强
dubbo怎么保证极高的扩展性?
基于SPI机制,核心的组件接口化,组件间的调用通过动态的查找配置的实现类
dubbo提供了一种自己实现组件的配置方式,没有找到配置的实现类就用默认的
Java原生SPI
核心理念就是扩展
比如你想以jar包的方式给某个接口提供实现,在你jar包中META-INF/services
目录下放一个跟接口同名的文件,里面标明你用哪个实现类去实现的,别人用了
这个接口的同时依赖了你的jar包就会在项目运行的时候走你的实现类
目录下放一个跟接口同名的文件,里面标明你用哪个实现类去实现的,别人用了
这个接口的同时依赖了你的jar包就会在项目运行的时候走你的实现类
缺点
一次性实例化扩展点所有实现,其中没用上也加载,很浪费资源
如果扩展点加载失败,就失败了,给用户没有任何通知
dubbo SPI
使用
比如想要扩展dubbo的负载均衡机制,先实现功能接口写实现类,搞一个jar包
在resources/META_INF/dubbo/下创建名称是接口名的文件,内容是key=实现类的全类名
在dubbo工程中依赖生成的jar包,并配置<dubbo:protocol loadbalance="key"/>
场景
dubbo自身的Protocol协议,负载均衡扩展,序列化扩展等,都是基于这种方式实现的
实现原理
ExtensionLoader
getExtension():主要用于获取名称为name的对应的子类的对象,
这里如果子类对象如果有AOP相关的配置,这里也会对其进行封装
这里如果子类对象如果有AOP相关的配置,这里也会对其进行封装
getAdaptiveExtension():使用定义的装饰类来封装目标子类,具体
使用哪个子类可以在定义的装饰类中通过一定的条件进行配置
使用哪个子类可以在定义的装饰类中通过一定的条件进行配置
getExtensionLoader():加载当前接口的子类并且实例化一个ExtensionLoader对象
优点
解决了上述Java原生SPI的缺点
增加了对扩展点 IoC 和 AOP 的支持
通信原理
网络通信
Netty
特点
高并发
Netty 是一款基于 NIO(Nonblocking IO,非阻塞IO)开发的网络通信框架
传输快
Netty 的传输依赖于零拷贝特性,尽量减少不必要的内存拷贝,实现了更高效率的传输
封装好
Netty 封装了 NIO 操作的很多细节,提供了易于使用调用接口
高性能
IO线程模型
点击跳转 👉
内存零拷贝
点击跳转 👉
内存池设计
申请的内存可以重用,主要指直接内存。内部实现是用二叉树管理内存分配情况
串形化处理读写
避免使用锁带来的性能开销
高性能序列化协议
支持 protobuf 等高性能序列化协议
mina
通信协议
dubbo协议(默认)
单一长连接和NIO异步通信
适合高并发小数据量(100k)的服务调用,消费者数量远大于提供者
rmi协议
支持Java二进制序列化,多个短连接
适合文件传输,以及消费者数量和提供者数量差不多
hessian协议
支持hessian序列化,占用带宽少,轻量效率高,多个短连接
适合文件传输,以及消费者数量小于提供者数量
http协议
支持json序列化,兼容性好,便于读写,占用带宽较大,传输效率较低
webservice协议,支持SOAP序列化
序列化协议
默认使用hessian序列化协议
采用二进制格式传输,占用带宽少,轻量效率高
其他系列化方式还有Java二进制、Json、SOAP等
负载均衡策略
Random LoadBalance
随机加权,按权重设置随机概率(默认)
RoundRobin LoadBalance
轮询,均匀的将流量打到各个机器上去,但是如果各个机器的性
能不同,容易导致性能差的机器负载过高,所以也需要配置权重
能不同,容易导致性能差的机器负载过高,所以也需要配置权重
存在慢服务器请求累积的问题
LeastActive LoadBalance
最少活跃数,通过自动感知,给性能较差的机器分配更少的请求
解决慢服务器请求积累
ConstantHash LoadBalance
一致性Hash,使相同参数请求被分发到同一提供者,服务提供者
挂掉的时候,会根据虚拟节点均匀分配剩余流量,抖动不会太大
挂掉的时候,会根据虚拟节点均匀分配剩余流量,抖动不会太大
集群容错方案
Failover Cluster
失败自动切换,自动重试其他服务器(默认)
通常用于读操作,但重试会带来更长延迟
Failfast Cluster
快速失败,立即报错,只发起一次调用
通常用于非幂等性的写操作,比如新增记录
Failsafe Cluster
失败安全,出现异常时,直接忽略
通常用于写入审计日志等操作
Failback Cluster
失败自动恢复,记录失败请求,定时重发
通常用于消息通知操作
Forking Cluster
并行调用多个服务器,只要一个成功即返回
通常用于实时性要求较高的读操作,但需要浪费更多服务资源
Broadcast Cluster
广播逐个调用所有提供者,任意一个报错则报错
通常用于通知所有提供者更新缓存或日志等本地资源信息
常见问题
说一下dubbo的工作原理?
首先dubbo通过注册中心解决服务的注册和发现,消费者是有个动态代理的概念的,底层要走一个负载均衡,
按照指定的协议组织请求然后进行Request的封装,最后通过netty网络通信框架将请求序列化后发送出去
按照指定的协议组织请求然后进行Request的封装,最后通过netty网络通信框架将请求序列化后发送出去
服务提供者通过网络通信框架实现了一个server监听端口,收到请求后进行反序列化,然后进行Request和
Protocol的解析,最后将请求转交给动态代理调用接口的实现类
Protocol的解析,最后将请求转交给动态代理调用接口的实现类
10层模型:接口层、配置层、代理层、注册层、集群层、监控层、协议层、交换层、传输层、序列化层
Dubbo的负载均衡策略有哪些?
随机加权、轮询(存在请求积累问题)、最少活跃数、一致性Hash
配置
Dubbo的集群容错策略有哪些?
失败重试、快速失败、失败安全、失败自动恢复、并行调用、广播调用
配置
dubbo集群容错方案如何选择?
读操作建议使用 Failover 失败自动切换,默认重试两次其他服务器
写操作建议使用 Failfast 快速失败,发一次调用失败就立即报错
Dubbo的动态代理策略有哪些?
默认使用javassist动态字节码生成,创建代理类,也可以通过SPI机制进行扩展
dubbo在安全机制方面如何做的?
dubbo 通过 token 令牌防止用户绕过注册中心直连,然后在注册
中心管理授权,还提供了黑白名单,控制服务所允许的调用方
中心管理授权,还提供了黑白名单,控制服务所允许的调用方
dubbo如何解决服务降级问题?
mock="true" 然后在接口的同一路径下创建接口的实现类编写降级逻辑
mock=force:return null 不发起远程调用直接返回null
mock=fail:return null 发起远程调用报错后,不抛错误,直接返回null
dubbo如何解决服务容错问题?
整合Hystrix,添加@HystrixCommand注解
dubbo远程调用高性能问题?
网络通信框架使用的基于NIO的Netty
dubbo如何解决服务扩展问题?
基于dubbo的SPI机制
dubbo如何保证服务高可用的?
搭建zookeeper集群
0 条评论
下一页