图1 AbstractDirectory有俩个实现类
前面几篇文章分析了Dubbo的核心工作原理,本篇将对之前涉及到但却未细讲的服务目录进行深入分析,在开始之前先结合前面的文章思考下什么是服务目录?它的作用是什么?
看起来像是黑白名单,但是实际是服务方通过zk通知过来的地址变成了EMPTY://这样的形式,通常我们会提供如下的解决方式
集群容错中的第二个关键词Router,中文意思就是路由 前端的路由和后端的路由他们是不同的,但是思想是基本一致的. 鉴于很多技术文章都有一个诟病,就是只讲概念,却不讲应用场景,其实Router在应用隔离,读写分离,灰度发布中都有它的影子.因此本篇用灰度发布的例子来做前期的铺垫
上篇文章《Dubbo之服务暴露》分析 Dubbo 服务是如何暴露的,本文接着分析 Dubbo 服务的消费流程。主要从以下几个方面进行分析:注册中心的暴露;通过注册中心进行服务消费通知;直连服务进行消费。服务消费端启动时,将自身的信息注册到注册中心的目录,同时还订阅服务提供方的目录,当服务提供方的 URL 发生更改时,实时获取新的数据。
前面文章分析了服务的导出与引用过程,从本篇文章开始,我将开始分析 Dubbo 集群容错方面的源码。这部分源码包含四个部分,分别是服务目录 Directory、服务路由 Router、集群 Cluster 和负载均衡 LoadBalance。这几个部分的源码逻辑比较独立,我会分四篇文章进行分析。本篇文章作为集群容错的开篇文章,将和大家一起分析服务目录相关的源码。在进行深入分析之前,我们先来了解一下服务目录是什么。服务目录中存储了一些和服务提供者有关的信息,通过服务目录,服务消费者可获取到服务提供者的信息,比如 ip、端口、服务协议等。通过这些信息,服务消费者就可通过 Netty 等客户端进行远程调用。在一个服务集群中,服务提供者数量并不是一成不变的,如果集群中新增了一台机器,相应地在服务目录中就要新增一条服务提供者记录。或者,如果服务提供者的配置修改了,服务目录中的记录也要做相应的更新。如果这样说,服务目录和注册中心的功能不就雷同了吗。确实如此,这里这么说是为了方便大家理解。实际上服务目录在获取注册中心的服务配置信息后,会为每条配置信息生成一个 Invoker 对象,并把这个 Invoker 对象存储起来,这个 Invoker 才是服务目录最终持有的对象。Invoker 有什么用呢?看名字就知道了,这是一个具有远程调用功能的对象。讲到这大家应该知道了什么是服务目录了,它可以看做是 Invoker 集合,且这个集合中的元素会随注册中心的变化而进行动态调整。
首先来看一下directory接口的实现类,他主要有两个实现类,一个是StaticDirectory,一个是RegistryDirectory,本文主要解析RegistryDirectory。
这两个引用服务的时机区别在于,第一个是饿汉式的,第二个是懒汉式的。 默认情况下,Dubbo 使用懒汉式引用服务。如果需要使用饿汉式,可通过配置 dubbo:reference 的 init 属性开启。
最近在生产环境和预发环境经常出现java.lang.IllegalStateException: urls to invokers error .invokerUrls.size :1, invoker.size :0,这一类的error错误,具体错误信息如下
dubbo PRC服务调用过程很复杂,这里准备通过分析一个典型rpc方法调用的调用栈来说明调用过程。说它典型,是因为本次分析的调用场景很典型简单 先定义一个接口 public interface DemoService { public String sayHello(String name); } 然后一个服务实现类 public class DemoServiceImpl implements DemoService { public String sayHello(S
RegistryDirectory,基于注册中心的服务发现,本文将重点探讨Dubbo是如何实现服务的自动注册与发现。从上篇文章,得知在消息消费者在创建服务调用器(Invoker)【消费者在初始时】时需要根据不同的协议,例如dubbo、registry(从注册中心获取服务提供者)来构建,其调用的方法为Protocol#refer,基于注册中心发现服务提供者的实现协议为RegistryProtocol。
Dubbo泛化调用特性可以在不依赖服务接口API包的场景中发起远程调用, 这种特性特别适合框架集成和网关类应用开发。
这回说说,dubbo路由特性,dubbo的路由干的事,就是一个请求过来, dubbo依据配置的路由规则,计算出哪些提供者可以提供这次的请求服务。 所以,它的优先级是在集群容错策略和负载均衡策略之前
在上篇在讲解源码分析Dubbo路由注册与发现机制的时候,dubbo管理员可以通过dubbo-admin管理系统在线上修改dubbo服务提供者的参数,最终将存储在注册中心的configurators catalog,然后通知RegistryDirectory更新服务提供者的URL中相关属性,按照最新的配置,重新创建Invoker并销毁原来的Invoker。
多个被调用者在调用时虚拟化为一个被调用者,这就是Dubbo的集群化,本文将从一次碰壁经历出发,讲一讲Dubbo是如何进行集群化的。
注:公众号关于dubbo解读文章均基于apache-dubbo-incubating-2.7.1版本,发版于5月26号,此版本注册中心(多数是zookeeper)在某些特殊场景下会出现重复URL地址数据无法删除,导致消费方拿到的是失效地址,从而导致调用失败的问题。如果你也在使用此版本进行源码学习,在网络漂移(下班回家再调试源码)的情况下需要手动删除zookeeper的dubbo节点路径
1)DubboConfigConfigurationRegistrar类的作用
上一篇中,我们介绍了dubbo的负载均衡实现,见识了几种常用的负载均衡算法。就单个功能而言,似乎dubbo并没有太多的突出之处。事实上,一个成功的产品不必每个地方都要打破常规。更重要的是其全局优化的架构设计,以及如何使用现有的优秀解决方案为己服务。
dubbo版本2.5.3 我们这里以zookeeper作为注册中心为例说明。 这里说的集群,可以理解为,一个接口服务对应有多个提供者。 在dubbo的调用方(reference)看来,每个提供方(service)对应一个invoker。 关于一个调用方对应多个提供方的场景大概包括三大类: 1,者调者订阅一个注册中心,此注册中心,同一个服务有多个提供者(以不同机器,端口,版本等发布的服务) 2,者调者订阅多个注册中心的服务,每个注册中心都有引用的服务的提供者(一个或者多个)。 3,调用方,通过url
相信经过前面几篇之后,大家已经对 Dubbo 整体流程已经清晰了,包括服务是如何暴露的,服务是什么时候注册到注册中心的,以及服务是怎么引入的,服务整体的调用过程等等。
虽然 Dubbo 是个很优秀的 SOA 框架,在国内也是非常流行,但在 service mesh 的大风下,有些跟不上时代了。一方面官方还没有给出权威的 mesh 化解决方案,另一方面,基于云原生的 Istio 确实太优秀,为了拥抱云原生,本文尝试罗列 dubbo 需要的改动,并基于 2.7.7 的源码实际尝试了去除 dubbo 路由和负载均衡功能。
zookeepeer的协议zab是Paxos变体,众所周知,Paxos是一个强一致性协议,需要经过多轮提议才能确定最终的共识。如果使用Zookeeper来进行存储,性能会惨不忍睹。
上一节我们主要讲解了利用dubbo-admin如何进行参数的动态修改,本节将重点介绍集群实现中另外一个实现细节:路由机制,Dubbo的路由机制主要解决的目的就是服务调用时,从已知的所有服务提供者中根据路由规则刷选服务提供者。
通过@EnableDubbo注解启动,该注解整合了@EnableDubboConfig和@DubboCompoentScan,这两个注解分别import了DubboConfigConfigurationRegistrar和DubboComponentScanRegistrar
dubbo-2.7.1-sources.jar!/org/apache/dubbo/rpc/proxy/InvokerInvocationHandler.java
前面的文章,已经单独对服务发现(Directory、RegistryDirectory)、路由机制(Router)、负载均衡机制(LoadBalance),本节将重点分析集群容错机制(AbstractClusterInvoker)。整个集群容错中,上述组件扮演的角色见下图所示,本文将重点分析AbstractClusterInvoker是如何融合这些组件的。
写在前面:2020年面试必备的Java后端进阶面试题总结了一份复习指南在Github上,内容详细,图文并茂,有需要学习的朋友可以Star一下! GitHub地址:https://github.com/abel-max/Java-Study-Note/tree/master
从dubbo的架构设计中,我们可以看出服务启动时,除了本地暴露服务之外会把服务注册到注册中心,那么作为消费端,在服务启动的时候则会向注册中心订阅需要调用的服务,然后在调用的时候通过注册中心拿到的地址做负载后选择合适的服务,然后建立连接并实现调用。
接上篇 https://cloud.tencent.com/developer/article/1109572 dubbo版本2.5.3 dubbo本身集群容错策略有7种。都实现了Cluster接口(
前两篇中,我们看到了dubbo在负载均衡和服务路由方面的实现,它为集群功能提供了必要的功能。
接上篇 https://cloud.tencent.com/developer/article/1109591 dubbo 版本2.5.3 通过代码可以看到failback,failover,failsafe,forking,failfast都通过了父类的select方法选择服务提供者(invoker) 这个方法里,也包含有dubbo处理集群的机制,包括使用负载均衡的策略。通知可以看到available和broadcast方案目前没用到负载均衡策略,先看先看select方法 /** * 使用lo
(1)生成Invoker对象。不同的Cluster实现会生成不同类型的ClusterInvoker对象并返回。然后调用ClusterInvoker的invoker方法,开始正式进入集群容错流程中。
为了避免单点故障,现在的应用至少会部署在两台服务器上。对于一些负载比较高的服务,会部署更多台服务器。这样,同一环境下的服务提供者数量会大于1。对于服务消费者来说,同一环境下出现了多个服务提供者。这时会出现一个问题,服务消费者需要决定选择哪个服务提供者进行调用。另外服务调用失败时的处理措施也是需要考虑的,是重试呢,还是抛出异常,亦或是只打印异常等。为了处理这些问题,Dubbo 定义了集群接口 Cluster 以及及 Cluster Invoker。集群 Cluster 用途是将多个服务提供者合并为一个 Cluster Invoker,并将这个 Invoker 暴露给服务消费者。这样一来,服务消费者只需通过这个 Invoker 进行远程调用即可,至于具体调用哪个服务提供者,以及调用失败后如何处理等问题,现在都交给集群模块去处理。集群模块是服务提供者和服务消费者的中间层,为服务消费者屏蔽了服务提供者的情况,这样服务消费者就可以处理远程调用相关事宜。比如发请求,接受服务提供者返回的数据等。这就是集群的作用。
将 Directory 中的多个 Invoker 伪装成一个 Invoker(伪装过程用到loadBalance),对上层透明,伪装过程包含了容错逻辑,调用失败后,重试另一个。简单来说,就是应对出错情况采取的策略。看看这个接口:
上一篇我们分析了服务发布的原理,可以看到默认是创建了一个Netty server,并通过Invoker调用服务,同样,在客户端也会创建一个Inovker对象,下面就一起来看看这个引用创建过程。
该文介绍Dubbo的服务引入.在Dubbo中,我们可以通过两种方式引用远程服务。第一种是使用服务直连的方式引用服务,第二种方式是基于注册中心进行引用.服务直连的方式仅适合在调试或测试服务的场景下使用,不适合在线上环境使用.因此,本文我将重点分析通过注册中心引用服务的过程. 运行 demo-dubbo--》dubbo-demo-api--》dubbo-demo-api-consumer 中 Application:
图1 Dubbo的ForkingClusterInvoker类继承图
dubbo-2.7.3/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ForkingClusterInvoker.java
图1 Dubbo的FailoverClusterInvoker类继承图
本文中,将进入消费端源码解析(具体逻辑会放到代码的注释中)。本文先是对消费过程的总体代码逻辑理一遍,个别需要细讲的点,后面会专门的文章进行解析。
本文简单介绍 Dubbo 中的 Failover Cluster(失败自动切换)。
上述通用逻辑代码被封装在AbstractDirectory中,主要干了以下两件事:
在消费端dubbo的使用中我们会把需要引用的provider服务配置在dubbo-consumer.xml中来进行引用,这一篇主要来分析dubbo的provider服务在消费端的服务引用。
实现了FactoryBean接口,所以在获取实例的时候,实际上是调用getObject方法返回实例。这里面的get方法继承自ReferenceConfig类
这篇说说,dubbo condition类型路由器的路由解析和执行过程 由 https://cloud.tencent.com/developer/article/1109552 这篇我们可以看到 condition类型路由器是由condition路由工厂获取,源码如下 public class ConditionRouterFactory implements RouterFactory { public static final String NAME = "condition";
1.check=true--系统在启动时就会去检查对应的dubbo服务,不存在就报错导致启动失败,所以如果设置为true,就必须确保该服务提供者一定要在该应用启动之前启动,否则就会启动失败
Export dubbo service com.ywl.dubbo.TestApi to local registry, dubbo version: 2.0.0, current host: 127.0.0.1。
领取专属 10元无门槛券
手把手带您无忧上云