zl程序教程

您现在的位置是:首页 >  其他

当前栏目

分布式专题 - Dubbo + Zookeeper

2023-03-31 10:38:35 时间

雪花算法的原理

第一位符号位固定为0,41位时间戳,10位workld,12位序列号,位数可以有不同实现
优点:

每个毫秒值包含的ID值很多,不够可以变动位数来增加,性能佳 (依赖workld的实现)。.时间戳值在高位,中间是固定的机器码,自增的序列在低位,整个ID是趋势递增的。0能够根据业务场景数据库节点布置灵活调整bit位划分,灵活度高。

缺点:
强依赖于机器时钟,如果时钟回拔,会导致重复的ID生成,所以一般基于此的算法发现时钟回拨,都会抛异常.
处理,阻止ID生成,这可能导致服务不可用。

为什么Zookeeper可以用来作为注册中心

可以利用Zookeeper的临时节点和watch机制来实现注册中心的自动注册和发现,另外Zookeeper中的数据都是存在内存中的,并且Zookeeper底层采用了nio,多线程模型,所以Zokeeper的性能也是比较高的,所以可以用来作为注册中心,但是如果考虑到注册中心应该是注册可用性的话,那么Zookeeper则不太合适,因为Zookeeper是CP的,它注重的是一致性,所以集群数据不-致时,集群将不可用,所以用Redis、Eureka、Nacos来作为注册中心将更合适。

数据库实现分布式锁的问题及解决方案

利用唯一约束键存储key,insert成功则代表获取锁成功,失败则获取失败,操作完成需要删除锁问题:
非阻塞,锁获取失败后没有排队机制,需要自己编码实现阻塞,可以使用自旋,直到获取锁;
不可重入,如果加锁的方法需要递归,则第二次插入会失败,可以使用记录线程标识解决重入问题;
死锁,删除锁失败、则其他线程没办法获取锁,可以设置超时时间、使用定时任务检查.
数据库单点故障,数据库高可用。

数据一致性模型有哪些

强一致性:当更新操作完成之后,任何多个后续进程的访问都会返回最新的更新过的值,这种是对用户最友好的,就是用户上一次写什么,下一次就保证能读到什么。根据 CAP 理论,这种实现需要牺牲可用性。
弱一致性: 系统在数据写入成功之后,不承诺立即可以读到最新写入的值,也不会具体的承诺多久之后可以读到。用户读到某一操作对系统数据的更新需要一段时间,我们称这段时间为“不一致性窗口”。
最终一致性:最终一致性是弱一致性的特例,强调的是所有的数据副本,在经过一段时间的同步之后,最终都能够达到一个一致的状态。因此,最终一致性的本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性。到达最终一致性的时间 ,就是不一致窗口时间,在没有故障发生的前提下,不一致窗口的时间主要受通信延迟,系统负载和复制副本的个数影响

最终一致性模型根据其提供的不同保证可以划分为更多的模型,包括因果一致性和会话一致性等。

因果一致性: 要求有因果关系的操作顺序得到保证,非因果关系的操作顺序则无所谓。
进程 A 在更新完某个数据项后通知了进程 B,那么进程 B 之后对该数据项的访问都应该能够获取到进程A更新后的最新值,并且如果进程 B 要对该数据项进行更新操作的话,务必基于进程 A 更新后的最新值。
在微博或者微信进行评论的时候,比如你在朋友圈发了一张照片,朋友给你评论了,而你对朋友的评论进行了回复,这条朋友圈的显示中,你的回复必须在朋友之后,这是一个因果关系,而其他没有因果关系的数据,可以允许不一致。
会话一致性:将对系统数据的访问过程框定在了一个会话当中,约定了系统能保证在同一个有效的会话中实现“读己之所写”"的一致性,就是在你的一次访问中,执行更新操作之后,客户端能够在同一个会话中始终读取到该数据项的最新值。实际开发中有分布式的 Session 一致性问题,可以认为是会话一致性的一个应用。

什么是分布式事务?有哪些实现方案?

在分布式系统中,一次业务处理可能需要多个应用来实现,比如用户发送一次下单请求,就涉及到订单系统创建订单、库存系统减库存,而对于一次下单,订单创与减库存应该界要同时成功或同时失败的,但在分布式系统中,如里不做处理,就很有可能出现订单创建成功,但界减库存失败,那么解决这类问题,就需要用到分布式事务。常用解决方案有:
1.本地消息表:创建订单时,将减库存消息加入在本地事务中,一起提交到数据库存入本地消息表,然后调用库存系统,如果调用成功则修改本地消息状态为成功,如果调用库存系统失败,则由后台定时任务从本地消息表中取出未成功的消息,重试调用库存系统
2.消息队列:目前RocketMQ中支持事务消息,它的工作原理是:
a.生产者订单系统先发送一条half消息到Broker,half消息对消费者而言是不可见的;
b.再创建单,根据创建订单成功与否,向Broker发送commit或rollback;
c 并且生产者订单系统还可以提供Broker回调接口,当Broker发现一段时间half消息没有收到任何操作命令,则会主动调此接口来查询订单是否创建成功;
d.一旦half消息commit了,消费者库存系统就会来消费,如果消费成功,则消息销毁,分布式事务成功结束;
e.如果消费失败,则根据重试策略进行重试,最后还失败则进入死信队列,等待进一步处理;
3.Seata:阿里开源的分布式事务框架,支持AT、TCC等多种模式,底层都是基于两阶段提交理论来实现的;

Zookeeper作为注册中心时,服务的加入和删除机制是怎么样的?

这个时候我们可以借助于Zookeeper的基本特性来实现一个注册中心,什么是注册中心,顾名思义,就是让众多的服务,都在Zookeeper中进行注册,啥是注册,注册就是把自己的一些服务信息,比如IP,端口,还有一些更加具体的服务信息,都写到 Zookeeper节点上, 这样有需要的服务就可以直接从zookeeper上面去拿,怎么拿呢? 这时我们可以定义统一的名称,比如,User-Service, 那所有的用户服务在启动的时候,都在User-Service 这个节点下面创建一个子节点(临时节点),这个子节点保持唯一就好,代表了每个服务实例的唯一标识,有依赖用户服务的比如Order-Service 就可以通过User-Service 这个父节点,就能获取所有的User-Service 子节点,并且获取所有的子节点信息(IP,端口等信息),拿到子节点的数据后Order-Service可以对其进行缓存,然后实现一个客户端的负载均衡,同时还可以对这个User-Service 目录进行监听, 这样有新的节点加入,或者退出,Order-Service都能收到通知,这样Order-Service重新获取所有子节点,且进行数据更新。这个用户服务的子节点的类型为临时节点。 第一节课有讲过,Zookeeper中临时节点生命周期是和SESSION绑定的,如果SESSION超时了,对应的节点会被删除,被删除时,Zookeeper 会通知对该节点父节点进行监听的客户端, 这样对应的客户端又可以刷新本地缓存了。当有新服务加入时,同样也会通知对应的客户端,刷新本地缓存,要达到这个目标需要客户端重复的注册对父节点的监听。这样就实现了服务的自动注册和自动退出。

ZAB的消息广播原理是什么?

ZAB 协议的消息广播过程使用的是一个原子广播协议,类似一个 两阶段提交过程。对于客户端发送的写请求,全部由 Leader 接收,Leader 将请求封装成一个事务 Proposal,将其发送给所有 Follwer ,然后,根据所有 Follwer 的反馈,如果超过半数(含leader自己)成功响应,则执行 commit 操作。
其他一些细节:
  1. Leader 在收到客户端请求之后,会将这个请求封装成一个事务,并给这个事务分配一个全局递增的唯一 ID,称为事务ID(ZXID),ZAB 协议需要保证事务的顺序,因此必须将每一个事务按照 ZXID 进行先后排序然后处理,主要通过消息队列实现。
  2. 在 Leader 和 Follwer 之间还有一个消息队列,用来解耦他们之间的耦合,解除同步阻塞。
  3. zookeeper集群中为保证任何所有进程能够有序的顺序执行,只能是 Leader 服务器接受写请求,即使是 Follower 服务器接受到客户端的写请求,也会转发到 Leader 服务器进行处理,Follower只能处理读请求。
  4. ZAB协议规定了如果一个事务在一台机器上被处理(commit)成功,那么应该在所有的机器上都被处理成功,哪怕机器出现故障崩溃。

崩溃恢复?

刚刚我们说消息广播过程中,Leader 崩溃怎么办?还能保证数据一致吗?
实际上,当 Leader 崩溃,即进入我们开头所说的崩溃恢复模式(崩溃即:Leader 失去与过半 Follwer 的联系)。下面来详细讲述。
假设1:Leader 在复制数据给所有 Follwer 之后,还没来得及收到Follower的ack返回就崩溃,怎么办?
假设2:Leader 在收到 ack 并提交了自己,同时发送了部分 commit 出去之后崩溃怎么办?
针对这些问题,ZAB 定义了 2 个原则:
  1. ZAB 协议确保丢弃那些只在 Leader 提出/复制,但没有提交的事务。
  2. ZAB 协议确保那些已经在 Leader 提交的事务最终会被所有服务器提交。
所以,ZAB 设计了下面这样一个选举算法:
能够确保提交已经被 Leader 提交的事务,同时丢弃已经被跳过的事务。
针对这个要求,如果让 Leader 选举算法能够保证新选举出来的 Leader 服务器拥有集群中所有机器 ZXID 最大的事务,那么就能够保证这个新选举出来的 Leader 一定具有所有已经提交的提案。
而且这么做有一个好处是:可以省去 Leader 服务器检查事务的提交和丢弃工作的这一步操作。

Zookeeper数据同步

当崩溃恢复之后,需要在正式工作之前(接收客户端请求),Leader 服务器首先确认事务是否都已经被过半的 Follwer 提交了,即是否完成了数据同步。目的是为了保持数据一致。
当 Follwer 服务器成功同步之后,Leader 会将这些服务器加入到可用服务器列表中。
实际上,Leader 服务器处理或丢弃事务都是依赖着 ZXID 的,那么这个 ZXID 如何生成呢?
答:在 ZAB 协议的事务编号 ZXID 设计中,ZXID 是一个 64 位的数字,其中低 32 位可以看作是一个简单的递增的计数器,针对客户端的每一个事务请求,Leader 都会产生一个新的事务 Proposal 并对该计数器进行 + 1 操作。
而高 32 位则代表了 Leader 服务器上取出本地日志中最大事务 Proposal 的 ZXID,并从该 ZXID 中解析出对应的 epoch 值(leader选举周期),当一轮新的选举结束后,会对这个值加一,并且事务id又从0开始自增。
高 32 位代表了每代 Leader 的唯一性,低 32 代表了每代 Leader 中事务的唯一性。同时,也能让 Follwer 通过高 32 位识别不同的 Leader。简化了数据恢复流程。
基于这样的策略:当 Follower 连接上 Leader 之后,Leader 服务器会根据自己服务器上最后被提交的 ZXID 和 Follower 上的 ZXID 进行比对,比对结果要么回滚,要么和 Leader 同步。

为什么可以在消费者一端统计最少活跃数?

  1. 消费者会缓存所调用服务的所有提供者,比如记为p1、p2、p3三个服务提供者,每个提供者内都有一个属性记为active,默认位0
  2. 消费者在调用次服务时,如果负载均衡策略是leastactive
  3. 消费者端会判断缓存的所有服务提供者的active,选择最小的,如果都相同,则随机
  4. 选出某一个服务提供者后,假设位p2,Dubbo就会对p2.active+1
  5. 然后真正发出请求调用该服务
  6. 消费端收到响应结果后,对p2.active-1
  7. 这样就完成了对某个服务提供者当前活跃调用数进行了统计,并且并不影响服务调用的性能

Dubbo消费者一端调用服务超时后,发送给服务端的任务会立即终止吗?

消费者调用一个服务,分为三步:

  1. 消费者发送请求(网络传输)
  2. 服务端执行服务
  3. 服务端返回响应(网络传输)

如果在服务端和消费端只在其中一方配置了timeout,那么没有歧义,表示消费端调用服务的超时时间,消费端如果超过时间还没有收到响应结果,则消费端会抛超时异常,服务端不会抛异常,服务端在执行服务后,会检查执行该服务的时间,如果超过timeout,则会打印一个超时日志。服务会正常的执行完。

集群容错和服务降级有什么区别?

  1. 集群容错是整个集群范围内的容错
  2. 服务降级是单个服务提供者的自身容错

本地存根是什么?

本地存根,名字很抽象,但实际上不难理解,本地存根就是一段逻辑,这段逻辑是在服务消费端执行的,这段逻辑一般都是由服务提供者提供,服务提供者可以利用这种机制在服务消费者远程调用服务提供者之前或之后再做一些其他事情,比如结果缓存,请求参数验证等等。

 本地伪装

本地伪装就是Mock,Dubbo中Mock的功能相对于本地存根更简单一点,Mock其实就是Dubbo中的服务容错的解决方案。

泛化服务和泛化调用

实现了GenericService接口的就是泛化服务。

泛化调用可以用来做服务测试。

在Dubbo中,如果某个服务想要支持泛化调用,就可以将该服务的generic属性设置为true,那对于服务消费者来说,就可以不用依赖该服务的接口,直接利用GenericService接口来进行服务调用。

Dubbo服务泛化调用的原理是什么

Dubbo 是一个分布式服务框架,其中包括了泛化调用的功能。泛化调用原理是基于动态代理实现的。
当客户端需要调用远程服务时,会先通过 Dubbo 的泛化代理工厂获取到一个泛化代理对象。这个代理对象会持有远程服务接口的全限定名称,并且会在调用时动态生成调用请求数据。这些数据包括调用方法名、参数类型、参数值等。然后通过 Dubbo 的网络通信层发送给服务端。
服务端收到请求后,会根据全限定名称获取到对应的服务实现类,然后根据请求中的方法名和参数类型进行反射调用。最后将结果返回给客户端。通过这种方式,客户端可以在不需要知道具体实现类的情况下调用远程服务,而服务端只需要暴露接口而不需要暴露实现类。这样可以提高系统的灵活性和可扩展性。

Dubbo SPI ExtentionLoader的loadClass方法做了哪些事?

loadClass方法

loadClass方法会做如下几件事情:

  1. 当前扩展点实现类上是否存在@Adaptive注解,如果存在则把该类认为是当前接口的默认自适应类(接口代理类),并把该类存到cachedAdaptiveClass属性上。
  2. 当前扩展点实现是否是一个当前接口的一个Wrapper类,如果判断的?就是看当前类中是否存在一个构造方法,该构造方法只有一个参数,参数类型为接口类型,如果存在这一的构造方法,那么这个类就是该接口的Wrapper类,如果是,则把该类添加到cachedWrapperClasses中去, cachedWrapperClasses是一个set
  3. 如果不是自适应类,或者也不是Wrapper类,则判断是有存在name,如果没有name,则报错。
  4. 如果有多个name,则判断一下当前扩展点实现类上是否存在@Activate注解,如果存在,则把该类添加到cachedActivates中,cachedWrapperClasses是一个map
  5. 最后,遍历多个name,把每个name和对应的实现类存到extensionClasses中去,extensionClasses就是上文所提到的map。

至此,加载类就走完了。

回到createExtension(String name)方法中的逻辑,当前这个接口的所有扩展点实现类都扫描完了之后,就可以根据用户所指定的名字,找到对应的实现类了,然后进行实例化,然后进行IOC(依赖注入)和AOP。

Dubbo服务导出大概原理

服务导出的入口为ServiceBean中的export()方法,当Spring启动完之后,通过接收Spring的ContextRefreshedEvent事件来触发export()方法的执行。

一个ServiceBean对象就表示一个Dubbo服务,ServiceBean对象中的参数就表示服务的参数,比如timeout,该对象的参数值来至@Service注解中所定义的。

服务导出主要得做两件事情:

  1. 根据服务的参数信息,启动对应的网络服务器(netty、tomcat、jetty等),用来接收网络请求
  2. 将服务的信息注册到注册中心

但是在做这两件事情之前得先把服务的参数确定好,因为一个Dubbo服务的参数,除开可以在@Service注解中去配置,还会继承Dubbo服务所属应用(Application)上的配置,还可以在配置中心或JVM环境变量中去配置某个服务的参数,所以首先要做的是确定好当前服务最终的(优先级最高)的参数值。

确定好服务参数之后,就根据所配置的协议启动对应的网络服务器。在启动网络服务器时,并且在网络服务器接收请求的过程中,都可以从服务参数中获取信息,比如最大连接数,线程数,socket超时时间等等。

启动完网络服务器之后,就将服务信息注册到注册中心。同时还有向注册中心注册监听器,监听Dubbo的中的动态配置信息变更。

服务导出要做的几件事情

  1. 确定服务的参数
  2. 确定服务支持的协议
  3. 构造服务最终的URL
  4. 将服务URL注册到注册中心去
  5. 根据服务支持的不同协议,启动不同的Server,用来接收和处理请求
  6. 因为Dubbo支持动态配置服务参数,所以服务导出时还需要绑定一个监听器Listener来监听服务的参数是否有修改,如果发现有修改,则需要重新进行导出

Dubbo服务参数配置的优先级

服务的参数可以从这四个位置来,这四个位置上如果配了同一个参数的话,优先级从高到低如下:

SystemConfiguration -> AppExternalConfiguration -> ExternalConfiguration -> AbstractConfig -> PropertiesConfiguration

为什么 Dubbo 不用JDK 的 SPI,而是要自己实现?
java spi缺点:
1、需要遍历所有实现并实例化,假设一个实现类初始化过程比较消耗资源且耗时,但是你的代码里面又用不上它,这就产生了资源的浪费。也无法准确引用;
2、没有使用缓存每次load都需要重新加载;
Dubbo sPI:
1、给每个实现类配了个名字,通过名字去文件里面找到对应的实现类全限定名然后加载实例化,按需加载。
2、增加了缓存存储实例,提高读取性能。
3、提供了对IOC和AOP等高级功能的支持,以实现更多类型的扩展。

什么是ZAB协议?

ZAB协议是Zookeeper用来实现一致性的原子广播协议,该协议描述了Zookeeper是如何实现一致性的,分为三个阶段:
1.领导者选举阶段:从Zookeeper集群中选出一个节点作为Leader,所有的写请求都会由Leader节点来处理
2.数据同步阶段:集群中所有节点中的数据要和Leader节点保持一致,如果不一致则要进行同步
3.请求广播阶段:当Leader节点接收到写请求时,会利用两阶段提交来广播该写请求,使得写请求像事务一样在其他节点上执行,达到节点上的数据实时一致
但值得注意的是,Zookeeper只是尽量的在达到强一致性,实际上仍然只是最终一致性的。

什么是CAP理论?

CAP理论是分布式领域中非常亚要的一个指导理论,C(Consisteny) 表示强一致性,A (Aailability) 表示可用性,(Partition Tolerance) 表示分区容错性,CAP理论指出在目前的硬件条件下,一个分布式系统是必须要保证分区容错性的,而在这个前提下,分布式系统要么保证CP,要么保证AP,无法同时保证CAP。
分区容错性表示,一个系统虽然是分布式的,但是对外看上去应该是一个整体,不能由于分布式系统内部的某个结点挂点,或网络出现了故障,而导致系统对外出现异常。所以,对于分布式系统而言是一定要保证分区容错性的。
强一致性表示,一个分布式系统中各个结点之间能及时的同步数据,在数据同步过程中,是不能对外提供服务的,不然就会造成数据不一致,所以强一致性和可用性是不能同时满足的。
可用性表示,一个分布式系统对外要保证可用.

如何实现接口的幂等性?

1. 唯一id。每次操作,都根据操作和内容生成唯一的id,在执行之前先判断id是否存在,如果不存在则执行后续操作,并且保存到数据库或者redis等;
2. 服务端提供发送token的接口,业务调用接口前先获取token,然后调用业务接口请求时,把token携带过去,务器判断token是否存在redis中,存在表示第一次请求,可以继续执行业务,执行业务完成后,最后需要把redis中的token删除;
3. 建去重表。将业务中有唯一标识的字段保存到去重表,如果表中存在,则表示已经处理过了。版本控制。增加版本号,当版本号符合时,才能更新数据;
4. 状态控制。例如订单有状态已支付 未支付 支付中 支付失败,当处于未支付的时候才允许修改为支付中等;

什么是BASE理论?

由于不能同时满足CAP,所以出现了BASE理论:
1.BA:Basically Available,表示基本可用,表示可以允许一定程度的不可用,比如由于系统故障,请求时间变长,或者由于系统故障导致部分非核心功能不可用,都是允许的;
2.s:Soft state:表示分布式系统可以处于一种中间状态,比如数据正在同步;
3.E:Eventualy consistent,表示最终一致性,不要求分布式系统数据实时达到一致,允许在经过一段时间后再达到一致,在达到一致过程中,系统也是可用的;

简述paxos算法?

Paxos算法解决的是一个分布式系统如何就某个值 (决议)达成一致。一个典型的场景是,在一个分布式数据库系统中,如果各个节点的初始状态一致,每个节点执行相同的操作序列,那么他们最后能够得到一个一致的状态。为了保证每个节点执行相同的操作序列,需要在每一条指令上执行一个"一致性算法”以保证每个节点看到的指令一致。在Paxos算法中,有三种角色: Proposer(提议者),Acceptor (接受者),Learners (记录员)
Proposer提议者: 只要Proposer发的提案Propose被半数以上的Acceptor接受,Proposer就认为该提案的value被选定了。
Acceptor接受者: 只要Acceptor接受了某个提案,Acceptor就认为该提案例的value被选定了。
Learner记录员: Acceptor告诉Learner哪个value被选定,Learner就认为哪个value被选定。
Paxos算法分为两个阶段,具体如下:
阶段一 (preprae ) :
(a) Proposer 收到client请求或者发现本地有未提交的值,选择一个提案编号 N,然后向半数以上的Acceptor 发送编号为 N的 Prepare 请求。
(b) Acceptor 收到一个编号为 N 的 Prepare 请求,如果该轮paxos:
本节点已经有已提交的value记录,对比记录的编号和N,大于N则拒绝回应,否则返回该记录value及编号;
没有已提交记录,判断本地是否有编号N1,N1>N、则拒绝响应,否则将N1改为N(如果没有N1,则记录N),并响应prepare。

阶段二 (accept) :
(a)如果 Proposer 收到半数以上 Acceptor 对其发出的编号为 N的 Prepare 请求的响应,那么它就会发送一个针对[N,V]提案的 Accept 请求给半数以上的 Acceptor。V 就是收到的响应中编号最大的value,如果响应中不包含任何value,那么V 就由 Proposer 自己决定。
(b) 如果 Acceptor 收到一个针对编号为 N 的提案的 Accept 请求,Acceptor对比本地的记录编号,如果小于等于N,则接受该值,并提交记录value。否则拒绝请求。
Proposer 如果收到的大多数Acceptor响应,则选定该value值,并同步给leaner,使未响应的Acceptor 达成一致。

如何理解RPC?
远程过程调用
RPC要求在调用方中放置被调用的方法的接口。调用方只要调用了这些接口,就相当于调用了被调用方的实际方法,十分易用。于是,调用方可以像调用内部接口一样调用远程的方法,而不用封装参数名和参数值等操作。包含:
1.动态代理,封装调用细节;
2. 序列化与反序列化,数据传输与接收;
3.通信,可以选择七层的http,四层的tcp/udp;
4.异常处理等;
首先,调用方调用的是接口,必须得为接口构造一个假的实现。显然,要使用动态代理。这样,调用方的调用就被
动态代理接收到了。
第二,动态代理接收到调用后,应该想办法调用远程的实际实现。这包括下面几步:
。识别具体要调用的远程方法的IP、端口;
。将调用方法的入参进行序列化;
。通过通信将请求发送到远程的方法中;

请谈谈ZooKeeper对事务性的支持
ZooKeeper对于事务性的支持主要依赖于四个函数,zoo_create_op_init,zoo_delete_op_init,zoo set op init以及zoo check op init。每一个函数都会在客户端初始化一个operation,客户端程序有义务保留这些operations。当准备好一个事务中的所有操作后,可以使用zoo_multi来提交所有的操作,由zookeeper服务来保证这一系列操作的原子性。也就是说只要其中有一个操作失败了,相当于此次提交的任何一个操作都没有对服务端的数据造成影响。zoo_multi的返回值是第一个失败操作的状态信号。

Dubbo的工作流程

1.Start: 启动Spring容器时,自动启动Dubbo的Provider
2.Register: Dubbo的Provider在启动后会去注册中心注册内容,注册的内容包括:IP、端口、接口列表(接口类、方法) 、版本、Provider的协议.
3.Subscribe: 订阅.当Consumer启动时,自动去Registry获取到所已注册的服务的信息.
4.Notify: 通知.当Provider的信息发生变化时,自动由Registry向Consumer推送通知.
5.Invoke: Consumer 调用Provider中方法.
5.1 同步请求消耗一定性能.但是必须是同步请求,因为需要接收调用方法后的结果;
6.Count:次数,每隔2分钟,Provoider和Consumer自动向Monitor发送访问次数Monitor进行统计;

简述你对RPC、RMI的理解

RPC: 在本地调用远程的函数,远程过程调用,可以跨语言实现 httpClient;
RMI:远程方法调用,java中用于实现RPC的一种机制,RPC的java版本,是J2EE的网络调用机制,跨JVM调用对象的方法,面向对象的思维方式;
直接或间接实现接口 java.rmi.Remote 成为存在于服务器端的远程对象,供客户端访问并提供一定的服务。
远程远程对象必须实现iava.rmi.server.UniCastRemoteobiect类,这样才能保证获得远程对象时, 该远程对象将会把自身的一个拷贝以Socket的形式传输给客户端,此时客户端所获得的这个拷贝称为“存根”,而服务器端本身已存在的远程对象则称之为"骨架"。其实此时的存根是客户端的一个代理,用于与服务器端的通信,而骨架也可认为是服务器端的一个代理,用于接收客户端的请求之后调用远程方法来响应客户端的请求。

简述raft算法

分布式一致性算法:raft会先选举出leaderleader完全负责replicated log的管理。leader负责接受所有客户.并在“安全”的时候执行这些请求。如果leader故障,followes会里新端更新请求,然后复制到follower节点,选举出新的leader;
概念:
三种状态: 一个节点任一时刻处于三者之-;
leader: 处理所有的客户端请求 (如果客户端将请求发给了Follower,Follower将请求重定向给Leader)。
follower: 不会发送任何请求,只会简单地响应来自Leader或Candidate的请求。
candidate: 用于选举产生新的leader(候选人)。
term: 任期,leader产生到重新选举为一任期,每个节点都维持着当前的任期号。
term是递增的,存储在log日志的entry中,代表当前entry是在哪一个term时期写入。
每个任期只能有一个leader或者没有(选举失败)。
每次rpc通信时传递该任期号,如果RPC收到任期号大于本地的、切换为follower,小于本地任期号则返回错误信息。

两个RPC通信:
RequestVote RPC: 负责选举,包含参数lastIndex,lastTerm
AppendEntries RPC: 负责数据的交互。
日志序列: 每一个节点上维持着一份持久化Log,通过一致性协议算法,保证每一个节点中的Log保持一致.并且顺序存放,这样客户端就可以在每一个节点中读取到相同的数据;
状态机: 日志序列同步到多数节点时,leader将该日志提交到状态机,并在下一次心跳通知所有节点提交状态机 (携带最后提交的lastIndex);


何时触发选举:
集群初始化时,都是follower,随机超时,变成candidate,发起选举;
如果follower在election timeout内没有收到来自leader的心跳,则主动触发;

选举过程:发出选举的节点角度
1、增加节点本地的term,切换到candidate状态
2、投自己一票
其他节点投票逻辑: 每个节点同一任期最多只能投一票,候选人知道的信息不能比自己少(通过副本日志和安全机制保障),先来先得
3、并行给其他节点发送RequestVote RPCs(选举请求)包含term参数
4、等待回复
4.1、收到majority(大多数)的投票,赢得选举,切换到leader状态,立刻给所有节点发心跳消息
4.2、被告知别人当选,切换到follower状态。 (原来的leader对比term,比自己的大,转换到follower状态)
4.3、一段时间没收到majority和leader的心跳通知,则保持candidate、重新发出选举

日志序列同步:日志需要存储在磁盘持久化,崩溃可以从日志恢复
1、客户端发送命令给Leader。
2、Leader把日志条目加到自己的日志序列里。
3、Leader发送AppendEntries RPC请求给所有的follower。携带了prevLoglndex,prevLogTermfollower收到后,进行日志序列匹配
匹配上则追加到自己的日志序列
匹配不上则拒绝请求,leader将日志index调小,重新同步直至匹配上,follower将leader的日志序列覆盖到本地

一旦新的日志序列条目变成majority的了,将日志序列应用到状态机中.
Leader在状态机里提交自己日志序列条目,然后返回结果给客户端;
Leader下次发送AppendEntries RPC时,告知follower已经提交的日志序列条目信息(lastindex);
follower收到RPC后,提交到自己的状态机里;
提交状态机时,如果term为上一任期,必须与当前任期数据一起提交,否则可能出现覆盖已提交状态机的日志;

 

讲下Zookeeper watch机制

客户端,可以通过在znode上设置watch,实现实时监听znode的变化Watch事件是一个一次性的触发器,当被设置了Watch的数据发生了改变的时候,则服务器将这个改变发送给设置了Watch的客户端。
父节点的创建,修改,删除都会触发Watcher事件.
子节点的创建,删除会触发Watcher事件
一次性:一旦被触发就会移除,再次使用需要重新注册,因为每次变动都需要通知所有客户端,一次性可以减轻压力,3.6.0默认持久递归,可以触发多次;
轻量: 只通知发生了事件,不会告知事件内容,减轻服务器和带宽压力;
Watcher 机制包括三个角色: 客户端线程、客户端的 WatchManager 以及 ZooKeeper 服务器
1.客户端向 ZooKeeper 服务器注册一个 Watcher 监听
2.把这个监听信息存储到客户端的 WatchManager 中
3.当 Zookeeper 中的节点发生变化时,会通知客户端,客户端会调用相应 Watcher 对象中的回调方法。watch回调是串行同步的

简述zk中的观察者机制?

peerType=observer
server.1:TocaThost:2181:3181:observer
观察者的设计是希望能动态扩展zookeeper集群又不会降低写性能。
如果扩展节点是follower,则写入操作提交时需要同步的节点数会变多,导致写入性能下降,而follower又是参与投票的、也会导致投票成本增加。
observer是一种新的节点类型,解决扩展问题的同时,不参与投票、只获取投票结果,同时也可以处理读写请求,写请求转发给leader。负责接收leader同步过来的提交数据,observer的节点故障也不会影响集群的可用性,
跨数据中心部署。把节点分散到多个数据中心可能因为网络的延迟会极大拖慢系统。使用observer的话,更新操作都在一个单独的数据中心来处理,并发送到其他数据中心,让其他数据中心的节点消费数据。
无法完全消除数据中心之间的网络延迟,因为observer需要把更新请求转发到另一个数据中心的leader,并外理同步消息,网络速度极慢的话也会有影响,它的优势是为本地读请求提供快速响应。

简述TCC事务模型?

TCC (补偿事务) : Try、Confirm、Cancel
针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作;
Try操作做业务检查及资源预留,Confirm做业务确认操作,Cancel实现一个与Trv相反的操作既回滚操作。TM首先发起所有的分支事务的try操作,任何一个分支事务的try操作执行失败,TM将会发起所有分支事务的Cancel操作,若try操作全部成功,TM将会发起所有分支事务的Confirm操作,其中onfirm/Cancel操作若执行失败,TM会进行重试。
TCC模型对业务的侵入性较强,改造的难度较大,每个操作都需要有 try、confirm、cancel三个接口实现;
TCC 中会添加事务日志,如果 Confirm 或者 Cancel 阶段出错,则会进行重试,所以这两个阶段需要支持幂等:如果重试失败,则需要人工介入进行恢复和处理等。

dubbo服务引入过程

饿汉式是通过调用 ReferenceBean的 afterPropertiesSet方法时引入服务。
懒汉式是只有当这个服务被注入到其他类中时启动引入流程,也就是说用到了才会开始服务引入。默认使用懒汉式,如果需要使用饿汉式,可通过配置dubbo:reference 的 init 属性开启。
ReferenceBean实现了FactoryBean接口,当对任意服务 lnterface 进行自动注入或者 getBean 获取时,就会触发 getObject()函数的服务引用过程。
  本地引入走 inivm 协议,到服务暴露的缓存中取exporter;
  直连远程引入服务,测试的情况下用,不需要启动注册中心,由 Consumer 直接配置写死 Provider 的地址,然后直连即可;
  注册中心引入远程服务,Consumer 通过注册中心得知 Provider 的相关信息,然后进行服务的引入;
获取注册中心实例,向注册中心注册自身,并订阅providers、configurators、routers 节点,触发Dubbolnvoker 的生成,cluster将多个服务调用者进行封装,返回一个invoker;
通过配置构建一个 map,然后利用 map 来构建 URL,再通过 URL 上的协议利用自适应扩展机制调用对应的protocol.refer 得到相应的 invoker 。然后再构建代理,封装 invoker 返回服务引用,之后 Comsumer 调用这个代理类。

 

dubbo服务暴露过程

Dubbo 采用 URL 的方式来作为约定的参数类型。
protoco1://username:password@host:port/path?key=value&key=value
protoco1: 指的是 dubbo 中的各种协议,如: dubbo thrift http
username/password: 用户名/密码
host/port:主机/端口
path: 接口的名称
parameters:参数键值对

ServiceBean实现了ApplicationListener,监听ContextRefreshedEvent事件,在 Spring 0C 容器刷新完成后调用onApplicationEvent方法,服务暴露的启动点。根据配置得到 URL,再利用 Dubbo SPI 机制根据 URL的参数选择对应的实现类,实现扩展。
通过 javassist 动态封装服务实现类,统一暴露出 invoker 使得调用方便、屏蔽底层实现细节,然后封装成exporter 存储起来,等待消费者的调用,并且会将 URL 注册到注册中心,使得消费者可以获取服务提供者的信息。
一个服务如果有多个协议那么就都需要暴露,比如同时支持 dubbo 协议和 hessian 协议,那么需要将这个服务用两种协议分别向多个注册中心 (如果有多个的话)暴露注册。

1、检测配置,如果有些配置空的话会默认创建,并且组装成 URL;
2、根据URL进行服务暴露、创建代理类invoker、根据URL得知具体的协议,根据Dubbo SPI选取实现类实现exporter;
3、如果只是本地暴露,将exporter 存入ServiceConfig的缓存;
4、远程暴露,先通过 registry 协议找到 RegistryProtocol 进行 export,将URL中export=dubbo://...先转换成exporter ,然后获取注册中心的相关配置,如果需要注册则向注册中心注册,并且在ProviderConsumerRegTable 这个表格中记录服务提供者,其实就是往一个ConcurrentHashMap 中将塞入invoker,key就是服务接口全限定名,value 是一个set,set 里面会存包装过的 invoker,根据URL上 Dubbo协议暴露出 exporter,打开 Server调用NettyServer 来监听服务

简述Dubbo的SPI机制

spi: service provider interface 服务发现机制通过接口全限定名找到指定目录下对应的文件,获取具体的实现类然后加载即可,做到了灵活的替换具体的实现类。

dubbo服务调用过程

调用某个接口的方法会调用之前生成的代理类,然后会从 cluster 中经过路由的过滤、负载均衡机制选择一个invoker 发起远程调用,此时会记录此请求和请求的 ID 等待服务端的响应。
服务端接受请求之后会通过参数找到之前暴露存储的 map,得到相应的 exporter ,然后最终调用真正的实现类再组装好结果返回,这个响应会带上之前请求的ID。
消费者收到这个响应之后会通过 D 去找之前记录的请求,然后找到请求之后将响应塞到对应的 Future 中,唤醒等待的线程,最后消费者得到响应。

负载均衡策略有哪些?

1、轮询法
将请求按顺序轮流地分配到后端服务器上,它均衡地对待后端的每一台服务器,而不关心服务器实际的连接数和当前的系统负载。
2、加权轮询法
不同的后端服务器可能机器的配置和当前系统的负载并不相同,因此它们的抗压能力也不相同。给配置高、负载低的机器配置更高的权重,让其处理更多的请,而配置低、负载高的机器,给其分配较低的权重,降低其系统负载,加权轮询能很好地处理这一问题,并将请求顺序且按照权重分配到后端。
3、随机法
通过系统的随机算法,根据后端服务器的列表大小值来随机选取其中的一台服务器进行访问。由概率统计理论可以得知,随着客户端调用服务端的次数增多,其实际效果越来越接近于平均分配调用量到后端的每一台服务器,也就是轮询的结果。
4、加权随机法
与加权轮询法一样,加权随机法也根据后端机器的配置,系统的负载分配不同的权重。不同的是,它是按照权重随机请求后端服务器,而非顺序。
5、源地址哈希法
源地址哈希的思想是根据获取客户端的IP地址,通过哈希函数计算得到的一个数值,用该数值对服务器列表的大小进行取模运算,得到的结果便是客服端要访问服务器的序号。采用源地址哈希法进行负载均衡,同一IP地址的客户端,当后端服务器列表不变时,它每次都会映射到同一台后端服务器进行访问。
6、最小连接数法
最小连接数算法比较灵活和智能,由于后端服务器的配置不尽相同,对于请求的处理有快有慢,它是根据后端服务器当前的连接情况,动态地选取其中当前积压连接数最少的一台服务器来处理当前的请求,尽可能地提高后端服务的利用效率,将负责合理地分流到每一台服务器。

分布式系统的设计目标

可扩展性: 通过对服务、存储的扩展,来提高系统的处理能力,通过对多台服务器协同工作,来完成单台服务器无法处理的任务,尤其是高并发或者大数据量的任务。
高可用: 单点不影响整体,单点故障指系统中某个组件一旦失效,会让整个系统无法工作
无状态:无状态的服务才能满足部分机器宕机不影响全部,可以随时进行扩展的需求
可管理:便于运维,出问题能不能及时发现定位
高可靠: 同样的请求返回同样的数据,更新能够持久化,数据不会丢失

分布式事务如何处理? 怎么保证事务一致性?

误区:分布式事务 = Seata
分布式事务: 就是要将不同节点上的事务操作,提供操作原子性保证。同时成功或者同时失败。
分布式事务第一个要点就是要在原本没有直接关联的事务之间建立联系。
1、HTTP连接: 最大努力通知。 -- 事后补偿
2、MQ : 事务消息机制。
3、Redis: 也可以定制出分布式事务机制。
4、Seata: 是通过TC来在多个事务之间建立联系。
两阶段: AT XA 就在于要锁资源。
三阶段: TCC 在两阶段的基础上增加一个准备阶段。在准备阶段是不锁资源的。
SAGA模式:类似于熔断。 业务自己实现正向操作和补偿操作的逻辑。

XA是资源层面的分布式事务,强一致性,在两阶段提交的整个过程中,一直会持有资源的锁。
TCC是业务层面的分布式事务,最终一致性,不会一直持有资源的锁。

分布式事务解决方案

XA规范: 分布式事务规范,定义了分布式事务模型。
四个角色: 事务管理器(协调者TM)、资源管理器(参与者RM),应用程序APP,通信资源管理器CRM
全局事务:一个横跨多个数据库的事务,要么全部提交、要么全部回滚。
JTA事务时iava对XA规范的实现,对应IDBC的单库事务。

第一阶段 ( prepare )每个参与者执行本地事务但不提交,进入 ready 状态,并通知协调者已经准备就绪。
第二阶段 (commit ) 当协调者确认每个参与者都 ready 后,通知参与者进行 commit 操作;如果有参与者fail则发送 rollback 命令,各参与者做回滚。

问题:

单点故障: 一旦事务管理器出现故障,整个系统不可用 (参与者都会阻塞住)。
数据不一致: 在阶段二,如果事务管理器只发送了部分 commit 消息,此时网络发生异常,那么只有部分参与者接收到 commit 消息,也就是说只有部分参与者提交了事务,使得系统数据不一致。
响应时间较长: 参与者和协调者资源都被锁住,提交或者回滚之后才能释放。
不确定性: 当协事务管理器发送 commit 之后,并且此时只有一个参与者收到了 commit,那么当该参与者与事务管理器同时宕机之后,重新选举的事务管理器无法确定该条消息是否提交成功。

三阶段协议: 主要是针对两阶段的优化,解决了2PC单点故障的问题,但是性能问题和不一致问题仍然没有根本解快

 

 总结:

基于XA协议的: 两阶段提交和三阶段提交,需要数据库层面支持;
基于事务补偿机制的: TCC,基于业务层面实现;
本地消息表: 基于本地数据库+mg,维护本地状态(进行中),通过mg调用服务,完成后响应一条消息回调,将状态改成完成。需要配合定时任务扫表、重新发送消息调用服务,需要保证幂等;
基于事务消息: mq;

分布式缓存寻址算法

hash算法: 根据key进行hash函数运算、结果对分片数取模,确定分片。
适合固定分片数的场景;
扩展分片或者减少分片时,所有数据都需要重新计算分片、存储;
一致性hash: 将整个hash值得区间组织成一个闭合的圆环,计算每台服务器的hash值、映射到圆环中。使用相同的hash算法计算数据的hash值,映射到圆环,顺时针寻找,找到的第一个服务器就是数据存储的服务器;
新增及减少节点时只会影响节点到他逆时针最近的一个服务器之间的值;
存在hash环倾斜的问题,即服务器分布不均匀,可以通过虚拟节点解决;
hash slot: 将数据与服务器隔离开,数据与slot映射,slot与服务器映射,数据进行hash决定存放的slot;
新增及删除节点时,将slot进行迁移即可。

分布式架构下,Session 共享有什么万案?

1、采用无状态服务,抛弃session。
2、存入cookie(有安全风险)
3、服务器之间进行 Session 同步,这样可以保证每个服务器上都有全部的 Session 信息,不过当服务器数量比较多的时候,同步是会有延迟甚至同步失败;
4、IP绑定策略:
使用 Nginx(或其他复杂均衡软硬件)中的IP 绑定策略,同一个IP 只能在指定的同一个机器访问,但是这样做失去了负载均衡的意义,当挂掉一台服务器的时候,会影响一批用户的使用,风险很大;
5、使用 Redis 存储
把Session 放到 Redis 中存储,虽然架构上变得复杂,并且需要多访问一次 Redis,但是这种方案带来的好处也是很大的:
实现了 Session 共享;
可以水平扩展(增加 Redis 服务器);
服务器重启 Session 不丢失(不过也要注意 Session 在 Redis 中的刷新/失效机制);。不仅可以跨服务器 Session 共享,甚至可以跨平台 (例如网页端和APP端)。

分布式id生成方案

1、uuid;
2、数据库自增序列;
3、美团提供的方案:leaf-segment,每次取出比如100个id,减少与数据库的交互。
4、基于redis、mongodb、zk等中间件生成;
5、雪花算法;

定时任务实现原理

优先队列:基于小顶堆实现,每次新增任务需要进行堆化,取任务时取堆顶元素、调整堆架构,时间复杂度是O(logN);
时间轮算法:是一个环形队列,按照时间的单位区分,每个时间单位里面是一个链表、用来存储定时任务,像时钟一样轮询环形队列,取出链表中的任务执行,如果超出了环形队列的时间粒度、可以使用多级时间轮,即使用不同维度的时间单位,就跟时钟或者水表一样,这一层的走了一圈,下一层的才走了一格,时间复杂度为O(1)。

Dubbo是如何做系统交互的?

Dubbo底层是通过RPC来完成服务和服务之间的调用的,Dubbo支持很多协议,比如赋认的dubbo协议,比如http协议、比rest等都是支持的,他们的底所使用的技术不太一样的,比如dubbo协议底层使用的是netty,也可以使用mina,http协议底层使用的tomcat或jetty。
服务消费老在调用某个服务时,会将当前所调用的服务接口信息 当前方法信息、执行方法所传入的入参信息等组装为一个invocation对象,然后不同的协议通时不同的教据组织方式和传输方式将这个对象传送给服务提供者,提供者接收到这个对象后,找到对应的服务实现,利用反射执行对应的方法,得到方法结果后再通过网络响应给服务消费者。
当然,Dubbo在这个调用过程中还做很多其他的设计,比如服务容错、负载均衡、Filter机制、动态路由机制等等,让Dubbo能处理更多企业中的需求。

Dubbo的负载均衡策略

Dubbo目前支持:
1.平衡加权轮询算法;
2.加权随机算法;
3.一致性哈希算法;
4.最小活跃数算法;

Zookeeper中的领导者选举的流程是怎样的?

对于Zookeeper集群,整个集群需要从集群节点中选出一个节点作为Leader,大体流程如下:
1,集群中各个节点首先都是观望状态(LOOKING),一开始都会投票给自己,认为自己比较适合作为leader;
2,然后相互交互投票,每个节点会收到其他节点发过来的选票,然后pk,先比较zxid,zxid大者获胜,zxid如果相等则比较myid,myid大者获胜;
3,一个节点收到其他节点发过来的选票,经过PK后,如果PK输了,则改票,此节点就会投给zxid或myid更大的节点,并将选票放入自己的投票箱中,并将新的选票发送给其他节点;
4,如果pk是平局则将接收到的选票放入自己的投票箱中;
5,如果pk赢了,则忽略所接收到的选票;
6,当然一个节点将一张选票放入到自己的投票箱之后,就会从投票箱中统计票数,看是否超过一半的节点都和自己所投的节点是一样的,如果超过半数,那么则认为当前自己所投的节点是leader。
7,集群中每个节点都会经过同样的流程,pk的规则也是一样的,一旦改票就会告诉给其他服务器,所以最终各个节点中的投票箱中的选票也将是一样的,所以各个节点最终选出来的leader也是一样的,这样集群的leader就选举出来了。

Zookeeper集群中节点之间数据是如何同步的

1,首先集群启动时,会先进行领导者选举,确定哪个节点是Leader,哪些节点是Follower和Observer;
2. 然后Leader会和其他节点进行数据同步,采用发送快照和发送Diff日志的方式;
3. 集群在工作过程中,所有的写请求都会交给Leader节点来进行处理,从节点只能处理读请求;
4. Leader节点收到一个写请求时,会通过两阶段机制来处理;
5. Leader节点会将该写请求对应的日志发送给其他Follower节点,并等待Follower节点持久化日志成功;
6. Follower节点收到日志后会进行持久化,如果持久化成功则发送一个Ack给Leader节点;
7. 当Leader节点收到半数以上的Ack后,就会开始提交,先更新Leader节点本地的内存数据;
8. 然后发送commit命令给Follower节点,Follower节点收到commit命令后就会爱新各色本地内存数据;
9,同时Leader节点还是将当前写请求直接发送给Observer节点,Observer节点收到Leader发过来的写请求后直接执行更新本地内存数据;
10.最后Leader节点返回客户端写请求响应成功;
11.通过同步机制和两阶段提交机制来达到集群中节点数据一致。

zk的会话管理机制?

客户端连接zk,有zk分配一个全局唯一的sessionld,客户端需要配置超时时间timeOut并传到zk,zk会据此计算会话下一次超时的时间点,zk根据这个时间点按照分桶策略进行分开存放,zk会给session设置一个isClosing属性,如果检测到超时会将该属性标记为关闭。
会话状态: CONNECTING、CONNECTED、RECONNECTING、RECONNECTED、CLOSE;
SessionTracker: zk中的会话管理器,负责会话的创建、管理和清理;
sessionsWithTimeout: 一个ConcurrentHashMap,用来管理会话的超时时间。
sessionsByld: HashMap,维护sessionld到session的映射
sessionsSets: HashMap,会话超时后进行归档,便于恢复和管理ExpiractionTime = CurrentTime + SessionTimeout
SessionTracker根据ExpiractionTime 将session进行分桶管理,同时按照一定的时间间隔进行定期检查,客户端读写请求都可以将session的超时时间重置,SessionTracker会将session进行分桶迁移,如果没有读写请求,客户需要发送ping心跳链接,否则session超时会被清除。

Spring Cloud和Dubbo的区别

底层协议: springcloud基于http协议,dubbo基于Tcp协议,决定了dubbo的性能相对会比较好。

注册中心: Spring Cloud 使用的 eureka ,dubbo推荐使用zookeeper。

模型定义: dubbo 将一个接口定义为一个服务,SpringCloud 则是将一个应用定义为一个服务。

SpringCloud是一个生态,而Dubbo是SpringCloud生态中关于服务调用一种解决方案 (服务治理)

选举算法Quorum 机制、WARO

waro:一种简单的副本控制协议,写操作时,只有当所有的副本都更新成功之后,这次写操作才算成功,否则视为失败。优先保证读、任何节点读到的数据都是最新数据,牺牲了更新服务的可用性、只要有一个副本宕机了,写服务就不会成功。但只要有一个节点存活、仍能提供读服务;
Quorum 机制: 10个副本,一次成功更新了三个,那么至少需要读取八个副本的数据,可以保证读到了最新的数据。无法保证强一致性,也就是无法实现任何时刻任何用户或节点都可以读到最近一次成功提交的副本数据。需要配合一个获取最新成功提交的版本号的 metadata 服务,这样可以确定最新已经成功提交的版本号,然后从已经读到的数据中就可以确认最新写入的数据。

dubbo中zk集群挂掉,发布者和订阅者还能通信么?

可以。
因为当启动dubbo容器时,消费者会去zookeeper拉取注册的生产者地址列表,并将其缓存在本地。每次发起调用时,都会按照本地的地址列表,以负载均衡的策略去进行调用。但是zookeeper挂掉则后续新的生产者无法被消费者发现。
。注册中心对等集群,任意一台宕掉后,会自动切换到另一台
。注册中心全部宕掉,服务提供者和消费者仍可以通过本地缓存通讯
。服务提供者无状态,任一台宕机后,不影响使用
。服务提供者全部宕机,服务消费者会无法使用,并无限次重连等待服务者恢复.

Dubbo是如何完成服务导出的?

1,首先Dubbo会将程序员所使用的@DubboService注解或@Service注解进行解析得到程序员所定义的服务参数,包括定义的服务名、服务接口、服务超时时间、服务协议等等,得到一个ServiceBean。
2,然后调用ServiceBean的export方法进行服务导出。
3,然后将服务信息注册到注册中心,如果有多个协议,多个注册中心,那就将服务按单个协议,单个注册中心进行注册。
4,将服务信息注册到注册中心后,还会绑定一些监听器,监听动态配置中心的变更。
5.还会根据服务协议启动对应的Web服务器或网络框架,比如Tomcat、Netty等.

Dubbo是如何完成服务引入的?

1,当程序员使用@Reference注解来引入一个服务时,Dubbo会将注解和服务的信息解析出来,得到当前所引用的服务名、服务接口是什么。
2,然后从注册中心进行查询服务信息,得到服务的提供者信息,并存在消费端的服务目录中。
3.并绑定一些监听器用来监听动态配置中心的变更。
4.然后根据查询得到的服务提供者信息生成一个服务接口的代理对象,并放入Spring容器中作为Bean。

dubbo集群容错策略有哪些

Failover Cluster失败自动切换: dubbo的默认容错方案,当调用失败时自动切换到其他可用的节点,具体的重试次数和间隔时间可通过引用服务的时候配置,默认重试次数为1也就是只调用一次。
Failback Cluster失败自动恢复: 在调用失败,记录日志和调用信息,然后返回空结果给consumer,并且通过定时任务每隔5秒对失败的调用进行重试。
Failfast cluster快速失败: 只会调用一次,失败后立刻抛出异常。
Failsafe Cluster失败安全: 调用出现异常,记录日志不抛出,返回空结果。
Forking Cluster并行调用多个服务提供者: 通过线程池创建多个线程,并发调用多个provider,结果保存到阻塞队列,只要有一个provider成功返回了结果,就会立刻返回结果。
Broadcast Cluster广播模式: 逐个调用每个provider,如果其中一台报错,在循环调用结束后,抛出异常。