随着微服务理论发展的成熟,越来越多互联网公司采用微服务架构来支持业务发展。然而不同公司又有各自的实现方式,本文主要是讲解注册中心原理和实际开发中的应用。
一、原理和功能
注册中心是隐藏在服务框架背后最基础的服务,记录各个服务的实例信息,决定业务服务是否正常调用
1.1 注册中心原理
注册中心主要涉及到三大角色 :注册中心、服务提供者 、服务消费者
三者关系流程描述如下:
1、各微服务启动时,将自己的实例信息(ip、端口、服务名等)注册到注册中心,注册中心存储这些数据
2、服务消费者从注册中心获取到服务提供者的实例信息,通过ip + 端口 方式远程调用服务提供者的接口
3、各个微服务通过心跳来上报注册中心,注册中心以某个时间段有没有接收到上报信息,来决定是否下线某服务实例
4、 微服务发生变动时如 增加实例或 ip变动,重新注册信息到注册中心。这样,服务消费者就无需改动,直接从注册中心获取最新信息即可
三者关系图 如下:
1.2 注册中心功能
1、服务注册表
服务注册表是注册中心的核心,它用来记录各个微服务实例的信息,例如微服务的名称、IP、端口等。服务注册表提供查询API和管理API,查询API用于查询可用的微服务实例,管理API用于服务的注册与注销。
2、服务注册与发现
服务注册是指微服务在启动时,将自己的信息注册到注册中心的过程。
服务发现是指查询可用的微服务列表及网络地址的机制。
3、服务检查
注册中心使用一定的机制定时检测已注册的服务,如发现某实例长时间无法访问,就会从服务注册表移除该实例。
二、主流选用组件
一个服务的提供者数量和分布是基于业务发展是动态变化的,注册中心需要支持弹性扩容,而这也体现了微服务的分布式属性。主流技术方向选用组件时,主要有 Eureka、Consul、ZooKeeper和Nacos这几种。这几种开源组件 都是基于分布式理论 CAP 的 CP 、AP 来实现的。
2.1 CAP理论
CAP理论是分布式架构实现中重要的理论
一致性(Consistency) : 所有节点在同一时间具有相同的数据
可用性(Availability) : 保证每个请求不管成功或者失败都有响应
分区容错(Partition tolerance) : 系统中任意信息的丢失或失败不会影响系统的继续运作
基于网络的不稳定性,分区容错是不可避免的,所以我们默认CAP中的P总是成立的。所以在此基础上,开源组件实现时 一般选择 一致性 (C)或 可用性(A)。
2.2 Eurake --> AP
Eurake是Netflix公司提供开源的,由Java语言开发,基于Restful Api风格 实现的服务注册和服务发现。不过 Netflix只开源到1.X版本,2.X版本已经关闭,不开放了。
Eureka 采用的是Server/Client的模式进行设计的。
Server是服务注册中心的角色,为Client提供服务的注册与发现功能,维护着注册到自身的Client的相关信息,同时提供接口给Client获取到注册表中的所有服务的信息。
Client将有关自己的服务的信息通过一定的方式登记在Server上,并在正常范围内维护自己信息的一致性,方便其他服务发现自己,同时可以通过Server获取到自己的依赖的其他服务信息,从而完成服务调用。
官网架构图:
Eurake架构
Application Service: 作为Eureka Client,扮演了服务的提供者,提供业务服务,向Eureka Server注册和更新自己的信息,同时能从Eureka Server的注册表中获取到其他服务的信息。
Eureka Server: 扮演服务注册中心的角色,提供服务注册和发现的功能,每个Eureka Cient向Eureka Server注册自己的信息,也可以通过Eureka Server获取到其他服务的信息达到发现和调用其他服务的目的。
Application Client: 作为Eureka Client,扮演了服务消费者,通过Eureka Server获取到注册到上面的其他服务的信息,从而根据信息找到所需的服务发起远程调用。
Replicate: Eureka Server中的注册表信息的同步拷贝,保持不同的Eureka Server集群中的注册表中的服务实例信息的一致性。提供了数据的最终一致性。
Make Remote Call: 服务之间的远程调用。
Register: 注册服务实例,Client端向Server端注册自身的元数据以进行服务发现。
Renew: 续约,通过发送心跳到Server维持和更新注册表中的服务实例元数据的有效性。当在一定时长内Server没有收到Client的心跳信息,将默认服务下线,将服务实例的信息从注册表中删除。
Cancel: 服务下线,Client在关闭时主动向Server注销服务实例元数据,这时Client的的服务实例数据将从Server的注册表中删除。
Eurake 没有使用强一致性哈希算法来实现不同集群之间的数据一致性,而是采用数据拷贝的方式争取注册中心数据的最终一致性。丢失了强一致性,提高了服务的可用性,提高了集群的健壮性。
2.3 Consul --> CP
Consul是由HashiCorp基于Go语言开发的支持多数据中心分布式高可用的服务发布和注册服务软件,采用Raft算法保证服务的一致性,且支持健康检查。
采用主从模式的设计,可以大规模的部署集群数据量,集群通过RPC方式来调用。
官网架构图:
Consul架构
Client:作为一个代理(非微服务实例),它将转发所有的RPC请求到Server中。作为相对无状态的服务,它不持有任何注册信息。
Server:作为一个具备扩展功能的代理,它将响应RPC查询、参与Raft选举、维护集群状态和转发查询给Leader等
Leader-Server:一个数据中心的所有Server都作为Raft节点集合的一部分。其中Leader将负责所有的查询和事务(如服务注册),同时这些事务也会被复制到所有其他的节点
Data Center:数据中心作为一个私有的,低延迟和高带宽的一个网络环境。每个数据中心会存在Consul集群,一般建议Server是3-5台(考虑到Raft算法在可用性和性能上取舍),而Leader只能唯一,Client的数量没有限制,可以轻松扩展。
Raft算法
Raft算法将Server分为三种类型:Leader、Follower和Candidate。
Leader处理所有的查询和事务,并向Follower同步事务。Follower会将所有的RPC查询和事务转发给Leader处理,它仅从Leader接受事务的同步。数据的一致性以Leader中的数据为准实现。
在节点初始启动时,节点的Raft状态机将处于Follower状态等待来来自Leader节点的心跳。如果在一定时间周期内没有收到Leader节点的心跳,节点将发起选举。
Follower节点选举时会将自己的状态切换为Candidate,然后向集群中其它Follower节点发送请求,询问其是否选举自己成为Leader。当收到来自集群中过半数节点的接受投票后,节点即成为Leader,开始接收Client的事务处理和查询并向其它的Follower节点同步事务。Leader节点会定时向Follower发送心跳来保持其地位。
Gossip协议
Gossip协议是为了解决分布式环境下监控和事件通知的瓶颈。Gossip协议中的每个Agent会利用Gossip协议互相检查在线状态,分担了服务器节点的心跳压力,通过Gossip广播的方式发送消息。
所有的Agent都运行着Gossip协议。服务器节点和普通Agent都会加入这个Gossip集群,收发Gossip消息。每隔一段时间,每个节点都会随机选择几个节点发送Gossip消息,其他节点会再次随机选择其他几个节点接力发送消息。这样一段时间过后,整个集群都能收到这条消息。
基于Raft算法,Consul提供强一致性的注册中心服务,但是由于Leader节点承担了所有的处理工作,势必加大了注册和发现的代价,降低了服务的可用性。通过Gossip协议,Consul可以很好地监控Consul集群的运行,同时可以方便通知各类事件,如Leader选择发生、Server地址变更等。
Consul虽然保证了强一致性,但是服务可用性就相应下降了。
如服务注册的时间稍长,因为 Consul 的 raft 协议要求必须过半数的节点都写入成功才认为注册成功 ;
如leader挂掉了之后,重新选举出leader之前会导致Consul 服务不可用
2.4 Zookeeper --> CP
Zookeeper 是Google开源的在Java语言上实现的分布式协调服务,是Hadoop和Hbase的重要组件,提供了数据/发布订阅、负载均衡、分布式同步等功能。Zookeeper 也是主从设计架构,搭建高可扩展的服务集群。
官网架构图:
Zookeeper架构
Leader-Server:Leader负责进行投票的发起和决议,更新系统中的数据状态
Server:Server中存在两种类型:Follower和Observer;其中Follower接受客户端的请求并返回结果(事务请求将转发给Leader处理),并在选举过程中参与投票;Observer与Follower功能一致,但是不参与投票过程,它的存在是为了提高系统的读取速度
Client:请求发起方,Server和Client之间可以通过长连接的方式进行交互。如发起注册或者请求集群信息等。
Zab协议
ZooKeeper Atomic Broadcast protocol是专门设计给Zookeeper用于实现分布式系统数据的一致性,是在Paxos算法基础上发展而来。它使用了单一的Leader来接受和处理客户端的所有事务请求,并将服务器数据的状态变更以事务Proposal的形式广播到所有的Server中。同时它保证Leader出现异常时,集群依旧能够正常工作。
Zab包含两种基本模式:崩溃恢复和消息广播。
崩溃恢复:Leader服务器出现宕机,或者因为网络原因导致Leader服务器失去了与过半 Follower的联系,那么就会进入崩溃恢复模式从而选举新的Leader。Leader选举算法不仅仅需要让Leader自己知道其自身已经被选举为Leader,同时还需要让集群中的所有其他服务器也能够快速地感知到选举产生的新的Leader。当选举产生了新的Leader,同时集群中有过半的服务器与该Leader完成了状态同步之后,Zab协议就会退出崩溃恢复模式,进入消息广播模式。
消息广播:Zab协议的消息广播过程类似二阶段提供过程,是一种原子广播的协议。当接受到来自Client的事务请求(如服务注册)(所有的事务请求都会转发给Leader),Leader会为事务生成对应的Proposal,并为其分配一个全局唯一的ZXID。Leader服务器与每个Follower之间都有一个单独的队列进行收发消息,Leader将生成的Proposal发送到队列中。Follower从队列中取出Proposal进行事务消费,消费完毕后发送一个ACK给Leader。当Leader接受到半数以上的Follower发送的ACK投票,它将发送Commit给所有Follower通知其对事务进行提交,Leader本身也会提交事务,并返回给处理成功给对应的客户端。Follower只有将队列中Proposal都同步消费后才可用。
基于Zab协议,Zookeeper可以用于构建具备数据强一致性的服务注册与发现中心,而与此相对地牺牲了服务的可用性和提高了注册需要的时间。
2.5 Nacos
Nacos 是阿里开源软件,支持基于 DNS 和基于 RPC 的服务发现。Nacos除了服务发现外,还有可以动态配置。让配置管理变得更加高效和敏捷,无需重启服务。
Nacos在特定条件下,会进行AP 、CP的切换。
2.6 对比
对比
三、Eurake实践分析
由于公司采用SpringCloud 全家桶组件进行开发,所以注册中心是 Eurake组件。
3.1 搭建注册中心服务
引入maven依赖 ,详见 附件 registry-center.xml
在Application.java 中 添加 @EnableEurekaServer 注解
Application.java
添加配置,详见 附件 application.properties
3.2 使用模式
主要有两种访问流程,一种是App访问服务时使用模式,另外一种是Client访问模式。
App访问
App访问
Client访问
Client访问
参考 :