一.概述
dubbo是一款经典的rpc框架,用来远程调用服务的。
dubbo的作用:
Dubbo 架构中的核心角色有哪些?
Dubbo 中的 Invoker 概念了解么?
Invoker
是 Dubbo 领域模型中非常重要的一个概念,你如果阅读过 Dubbo 源码的话,你会无数次看到这玩意。就比如下面我要说的负载均衡这块的源码中就有大量 Invoker
的身影。
简单来说,Invoker
就是 Dubbo 对远程调用的抽象。分为2种:
服务提供 Invoker
服务消费 Invoker
我们需要调用一个远程方法,我们需要动态代理来屏蔽远程调用的细节吧!我们屏蔽掉的这些细节就依赖对应的 Invoker
实现, Invoker
实现了真正的远程服务调用
Dobbo的分层架构(工作原理)
ServiceConfig
, ReferenceConfig
为中心ServiceProxy
为中心。Invoker
为中心。Statistics
为中心。Invocation
, Result
为中心。Request
, Response
为中心。Message
为中心。Dubbo 的 SPI 机制了解么?
为什么 Dubbo 不用 JDK 的 SPI,而是要自己实现?
如果想深入研究Java SPI:请看一位大佬写的文章:SPI源码分析
如何扩展 Dubbo 中的默认实现?
XxxLoadBalance
实现 LoadBalance
接口或者 AbstractLoadBalance
类。resources
目录下的 META-INF/dubbo/org.apache.dubbo.rpc.cluster.LoadBalance
文件中即可。public class XxxLoadBalance implementsLoadBalance {
public <T> Invoker<T> select(List<Invoker<T>> invokers, Invocation invocation) throwsRpcException {
//...
}
}
** 三.Dubbo 的负载均衡策略**
服务暴露**:生成代理类,**将信息注册到ZK
组装URL:Spring IOC 容器刷新完毕之后,会根据配置参数组装成 URL, 然后根据 URL 的参数来进行代理类的生成。
生成代理类:会通过 proxyFactory.getInvoker
,利用 javassist 来进行动态代理,封装真的实现类。
根据协议生成暴露对象(exporter):通过 URL 参数选择对应的协议来进行 protocol.export,默认是 Dubbo 协议。
自适应:代理类会根据 Invoker 里面的 URL 参数得知具体的协议,然后通过 Dubbo SPI 机制选择对应的实现类进行 export。
注册到ZK:将 export 得到的 exporter 存入一个 Map 中,供之后的远程调用查找,然后会向注册中心注册提供者的信息。
想要深究源码的小伙伴可以看一位大佬写的文章:服务暴露源码分析。
服务引用:获取远程调用的类,生成代理类。可以看作服务引用的逆过程。
组装URL:会根据配置参数组装成 URL, 然后根据 URL 的参数来进行代理类的生成。(2种时机)
饿汉式:饿汉式是通过实现 Spring 的InitializingBean
接口中的 afterPropertiesSet
方法,容器通过调用 ReferenceBean
的 afterPropertiesSet
方法时引入服务。(在Spring启动时,给所有的属性注入实现类,包含远程和本地的实现类)
懒汉式:只有当这个服务被注入到其他类中时启动引入流程,也就是说用到了才会开始服务引入。
在应用的Spring Context初始化完成事件时触发,扫描所有的Bean,将Bean中带有@Reference注解的field获取到,然后创建field类型的代理对象,创建完成后,将代理对象set给此field。后续就通过该代理对象创建服务端连接,并发起调用。(dubbo默认)
从ZK中获取需要的服务提供者的信息:得到Map。
根据协议解析传过来的exporter:
协议的不同,获取的路径也不同:本地,直接,从ZK。
想要深究源码的小伙伴可以看一位大佬写的文章:服务引用源码分析。
服务调用:
服务调用是在生成代理对象后,使用Netty,生成Netty Client进行远程调用。Netty Server通过反射返回调用结果。
在调用之前,就会进行智能容错和负载均衡。
首先客户端调用接口的某个方法,实际调用的是代理类,代理类会通过 cluster 从 directory(invoker的集合) 中获取一堆 invokers(如果有一堆的话),然后进行 router 的过滤(其中看配置也会添加 mockInvoker 用于服务降级),然后再通过 SPI 得到 loadBalance 进行一波负载均衡。
补充:cluster 是什么?
想要深究源码的小伙伴可以看一位大佬写的文章:服务调用源码分析。
容错机制:先容错,再负载均衡。
dubbo常见的容错机制
Failover Cluster(默认)
失败自动切换,当出现失败,重试其它服务器。
通常用于读操作,但重试会带来更长延迟。
Failfast Cluster
快速失败,只发起一次调用,失败立即报错。
通常用于非幂等性的写操作,比如新增记录。
Failsafe Cluster
失败安全,出现异常时,直接忽略。
通常用于写入审计日志等操作。
Failback Cluster
失败自动恢复,后台记录失败请求,定时重发。
通常用于消息通知操作。
Forking Cluster
并行调用多个服务器,只要一个成功即返回。
通常用于实时性要求较高的读操作,但需要浪费更多服务资源。
想要深究源码的小伙伴可以看一位大佬写的文章:dubbo智能容错源码分析
五.其他小问题
Dubbo 为什么默认用 Javassist?
很简单,就是快,且字节码生成方便。
其他常见的动态代理: JDK 的动态代理、ASM、cglib。
ASM 比 Javassist 更快,但是没有快一个数量级,而Javassist 只需用字符串拼接就可以生成字节码,而 ASM 需要手工生成,成本较高,比较麻烦。
Dubbo 支持多种序列化方式?
寄语:你所看到的惊艳,都曾被平庸历练
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://www.cnblogs.com/monkey-xuan/p/15887368.html
内容来源于网络,如有侵权,请联系作者删除!