美文网首页
RPC(六:服务发现)

RPC(六:服务发现)

作者: supremecsp | 来源:发表于2022-06-20 14:08 被阅读0次

RPC调用就是把拦截到的方法参数,转成可以在网络中传输的二进制,并保证在服务提供方能正确地还原出语义,最终实现像调用本地一样地调用远程的目的。

假设有用到 Spring 的话,我们希望 RPC 能让我们把一个 RPC 接口定义成一个 Spring Bean,并且这个 Bean 也会统一被 Spring Bean Factory 管理,可以在项目中通过 Spring 依赖注入到方式引用。这是 RPC 调用的入口,我们一般叫做 Bootstrap 模块。
当服务器通过FeignClient和RequestMapping将接口暴露出去后,客户端通过@Autowired引入即可使用。

服务发现
同一个接口有着多个服务提供者,但这多个服务提供者对于我们的调用方来说是透明的,所以在 RPC 里面我们还需要给调用方找到所有的服务提供方,并需要在 RPC 里面维护好接口跟服务提供者地址的关系,这样调用方在发起请求的时候才能快速地找到对应的接收地址。
常用于实现服务发现有eureka和zookeeper。称为注册中心。

RPC 框架的服务发现机制:



服务注册:在服务提供方启动的时候,将对外暴露的接口注册到注册中心之中,注册中心将这个服务节点的 IP 和接口保存下来。
服务订阅:在服务调用方启动的时候,去注册中心查找并订阅服务提供方的 IP,然后缓存到本地,并用于后续的远程调用。

DNS可否作为服务发现?
DNS作为服务注册发现的一种方案,它比较简单。只要在DNS服务上,配置一个DNS名称与IP对应关系即可。定位一个服务只需要连接到DNS服务器上,随机返回一个IP地址即可。由于存在DNS缓存,所以DNS服务器本身不会成为一个瓶颈。
这种基于Pull的方式不能及时获取服务的状态的更新(例如:服务的IP更新等)。
如果服务的提供者出现故障,由于DNS缓存的存在,服务的调用方会仍然将请求转发给出现故障的服务提供方。

CAP定理
在分布式领域有一个很著名的CAP定理:C:数据一致性。A:服务可用性。P:分区容错性(服务对网络分区故障的容错性)。
在这个特性中任何分布式系统只能保证两个。



CAP理论也就是说在分布式存储系统中,最多只能实现以上两点。而由于当前网络延迟故障会导致丢包等问题,所以我们分区容错性是必须实现的。
也就是NoSqL数据库P肯定要有,我们只能在一致性和可用性中进行选择,没有Nosql数据库能同时保证三点。(==>AP 或者 CP)
Eureka和Zookeeper就是CAP定理中的实现,Eureka(保证AP),Zookeeper(保证CP)。

1. Zookeeper保证CP
当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的注册信息,但不能接受服务直接down掉不可用。也就是说,服务注册功能对可用性的要求要高于一致性。但是zk会出现这样一种情况,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举。问题在于,选举leader的时间太长,30 ~ 120s, 且选举期间整个zk集群都是不可用的,这就导致在选举期间注册服务瘫痪。在云部署的环境下,因网络问题使得zk集群失去master节点是较大概率会发生的事,虽然服务能够最终恢复,但是漫长的选举时间导致的注册长期不可用是不能容忍的。
2. Eureka保证AP
Eureka看明白了这一点,因此在设计时就优先保证可用性。Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册或时如果发现连接失败,则会自动切换至其它节点,只要有一台Eureka还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。除此之外,Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:
1,Eureka不再从注册列表中移除因为长时间没收到心跳而应该过期的服务
2,Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用)
3,当网络稳定时,当前实例新的注册信息会被同步到其它节点中
Eureka与Zookeeper对比,分布式注册中心 Eureka 与 zookeeper 的区别、原理及各自优缺点

Zooekeeper 基本原理
ZooKeeper 是以 Paxos 算法为基础的,而Paxos 算法存在活锁的问题,即当有多个 proposer 交错提交时,有可能互相排斥导致没有一个 proposer 能提交成功,而 Paxos 作了一些优化,通过选举产生一个leader (领导者),只有 leader 才能提交 proposer。

*注:所谓的 Paxos 算法是一种基于消息传递的一致性算法,并且该算法被认为是类似算法中最有效的。
ZooKeeper 的基本运行流程:
1、选举 Leader(所以一般要求3个,或者以上)。
2、同步数据。
3、选举 Leader 过程中算法有多中,但最终的选举标准是一致的。
4、Leader 被赋予最高的执行ID(竞选成功后的授权),其执行ID类似于Linux中的root权限。
5、集群中服务得到通知并一致的认可选出的 Leader。
6、Leader 服务器宕机,进入1)步,再次进行 Leader 选举。
Zookeeper 获取服务列表时,如果此时的 Zookeeper 集群中的 Leader 宕机了,该集群就要进行 Leader 的选举,又或者 Zookeeper 集群中半数以上服务器节点不可用(例如有三个节点,如果节点一检测到节点三挂了 ,节点二也检测到节点三挂了,那这个节点才算是真的挂了),那么将无法处理该请求。所以说,Zookeeper 不能保证服务可用性。

Eureka
Eureka 可以运行多个实例来构建集群,解决单点问题,但不同于 ZooKeeper 的选举 leader 的过程,Eureka Server 采用的是Peer to Peer 对等通信。无 master/slave 之分,每一个 Peer 都是对等的。在这种架构风格中,节点通过彼此互相注册来提高可用性,每个节点需要添加一个或多个有效的 serviceUrl 指向其他节点。每个节点都可被视为其他节点的副本。
当一个新的 Eureka Server 节点启动后,会首先尝试从邻近节点获取所有注册列表信息,并完成初始化。Eureka Server 通过 getEurekaServiceUrls() 方法获取所有的节点,并且会通过心跳契约的方式定期更新。默认情况下,如果 Eureka Server 在一定时间内没有接收到某个服务实例的心跳(默认周期为30秒),Eureka Server 将会注销该实例(默认为90秒,如果某个 eureka.instance.lease-expiration-duration-in-seconds 进行自定义配置)。当 Eureka Server 节点在短时间内丢失过多的心跳时,那么这个节点就会进入自我保护模式
Eureka还有客户端缓存功能(注:Eureka分为客户端程序与服务器端程序两个部分,客户端程序负责向外提供注册与发现服务接口)。所以即便Eureka集群中所有节点都失效,或者发生网络分割故障导致客户端不能访问任何一台Eureka服务器;Eureka服务的消费者仍然可以通过Eureka客户端缓存来获取现有的服务注册信息。甚至最极端的环境下,所有正常的Eureka节点都不对请求产生相应,也没有更好的服务器解决方案来解决这种问题时;得益于Eureka的客户端缓存技术,消费者服务仍然可以通过Eureka客户端查询与获取注册服务信息,这点很重要。

接下来摘抄文章部分内容:Spring Cloud Eureka 原理分析
Eureka Server 负责管理整个集群服务实例信息,有新实例注册时需要为其创建和管理对应的 Lease ,同时还负责把 Lease 的变更同步给集群中其他的 Eureka Server,以保证集群中所有的 Eureka Server 节点的服务列表最终一致。Eureka Server 会把这些 Lease 维护在一个 PeerAwareInstanceRegistry 里,当有 Eureka Client 需要获取服务列表时,需要从中获取这些 Lease 信息返回。

Eureka Server 的接口支持以 JSON 和 XML 的格式返回数据,还支持对数据压缩。Eureka Client 在获取服务列表时,Eureka Server 会把服务实例信息按请求的格式序列化和压缩后返回。当集群里 Eureka Client 比较多时,如果每次返回响应时都去做序列化和压缩,那么就会浪费资源在重复的操作上。Eureka Server 对响应做了缓存,这样在处理 Eureka Client 请求时就可以直接从缓存获得已经序列化完成和压缩完成的数据返回了。

Eureka Client 在和 Eureka Server 通讯之前,需要先获得 Eureka Server 的地址。如果 Eureka Server 是多实例部署的,那么还需要对这些地址做优先级排序,然后 Eureka Client 在发起调用时会按顺序调用,失败时再尝试下一个 Eureka Server。

SessionedEurekaHttpClient 装饰了 RetryableEurekaHttpClient 并为其创建一个 session。当 session 时间过后,RetryableEurekaHttpClient 会被重新创建。
这样做的目的是为了使集群中 Eureka Server 节点的负载尽量平均。假设现在集群里添加了一个新的 Eureka Server 节点,如果创建新 的 client,那么除非发生异常切换,否则现有的 Eureka Client 还是会把请求发到老的 Eureka Server 节点,而新的节点不会收到请求。SessionedEurekaHttpClient 在当前 session 结束创建新 session 时给了 Eureka Client 重新选择 Eureka Server 的机会,能让集群里的 Eureka Client 尽量连接到不同的 Eureka Server。
session 的时长可以通过配置设置。默认情况下 session 的时长范围是 10 到 30 分钟。

由于正常情况下集群中大部分的服务实例信息不会发生变化,所以没有必要每次在更新时都全量拉取服务列表。Eureka Client 在更新服务列表缓存时会优先使用增量更新的方式。



Eureka Server 在返回增量信息时还会同时返回 Eureka Server 服务列表的 hashcode 。Eureka Client 更新完本地缓存之后也会计算本地的 hashcode 并和 Eureka Server 返回的比较。如果两者不同,那么说明本地缓存的数据和 Eureka Server 出现差异了,此时 Eureka Client 会再发起全量获取服务列表的请求,以保证本地缓存和 Eureka Server 的一致。这样就解决了第一个问题。另外,每次更新完本地缓存后还会对服务实例列表做随机重排,这样做是为了避免不同的 Eureka Client 都优先使用相同的实例。

关于ZooKeeper集群脑裂及其解决方案
Zookeeper集群"脑裂":
假死:由于心跳超时(网络原因导致的)认为 leader 死了,但其实 leader 还存活着。
脑裂:由于假死会发起新的 leader 选举,选举出一个新的 leader,但旧的 leader 网络又通了,导致出现了两个 leader ,有的客户端连接到老的 leader,而有的客户端则连接到新的 leader。

zookeeper是如何解决"脑裂"问题的:
zooKeeper 默认采用了 Quorums 这种方式来防止"脑裂"现象,即只有集群中超过半数节点投票才能选举出 Leader。这样的方式可以确保 leader 的唯一性,要么选出唯一的一个 leader,要么选举失败。在 zookeeper 中 Quorums 有2个作用:
1,集群中最少的节点数用来选举 leader 保证集群可用。
2,通知客户端数据已经安全保存前集群中最少数量的节点数已经保存了该数据。一旦这些节点保存了该数据,客户端将被通知已经安全保存了,可以继续其他任务。而集群中剩余的节点将会最终也保存了该数据。

假设某个 leader 假死,其余的 followers 选举出了一个新的 leader。这时,旧的leader 复活并且仍然认为自己是 leader,这个时候它向其他 followers 发出写请求也是会被拒绝的。因为每当新 leader 产生时,会生成一个 epoch 标号(标识当前属于那个 leader 的统治时期),这个epoch是递增的,followers 如果确认了新的leader 存在,知道其 epoch,就会拒绝 epoch 小于现任 leader epoch 的所有请求。那有没有 follower 不知道新的 leader 存在呢,有可能,但肯定不是大多数,否则新 leader 无法产生。Zookeeper 的写也遵循 quorum 机制,因此,得不到大多数支持的写是无效的,旧 leader 即使各种认为自己是 leader,依然没有什么作用。

相关文章

  • RPC(六:服务发现)

    RPC调用就是把拦截到的方法参数,转成可以在网络中传输的二进制,并保证在服务提供方能正确地还原出语义,最终实现像调...

  • RPC服务注册&发现

    如何发布自己的服务? RPC远程过程调用中,存在2个角色,一个服务提供者、另一个服务消费者。那如何让调用者知道,存...

  • 服务发现

    参考老钱 服务发现的基本原理服务发现聊聊 Node.js RPC(二)— 服务发现 在传统的系统部署中,服务运行在...

  • 康过来!Nacos配置和管理微服务的使用

    Nacos 具有如下特性: 服务发现和服务健康监测:支持基于DNS和基于RPC的服务发现,支持对服务的实时的健康检...

  • Dubbo

    Dubbo(服务治理框架) RPC 各服务都要实现rpc协议,才能实现服务间的调用 rpc:远程过程调用协议,是一...

  • 搭建、挂载nfs及卸载

    搭建 1、 安装 nfs 和 rpc 2、运行 rpc 和 nfs (先启动RPC服务,然后再启动NFS服务) ...

  • 基于Netty的高性能JAVA的RPC框架

    RPC的实现 1. RPC客户端 2. RPC服务端 RPC客户端的实现 RPC客户端和RPC服务器端需要一个相同...

  • (极客时间)rpc服务发现

    服务发现图片补充1、服务发现流程图: 2、DNS流程 3、zookeeper服务发现结构 4、 总线注册流程

  • 架构师凭什么拿60万年薪?从微服务框架说起

    微服务架构专题 RPC原理 RPC是什么? RPC(Remote Procedure Call Protocol)...

  • SpringBoot Nacos 作为注册中心

    简介 Nacos 支持基于 DNS 和基于 RPC 的服务发现。服务提供者使用 原生SDK[https://nac...

网友评论

      本文标题:RPC(六:服务发现)

      本文链接:https://www.haomeiwen.com/subject/ozqhvrtx.html