Eureka服务注册和发现
一. Eureka简介
1. 什么是Eureka?
Spring Cloud Eureka是Spring Cloud Netflix微服务套件中的一部分,它基于Netflix Eureka做了二次封装,是Netflix项目下的服务治理模块,主要负责完成微服务架构中的服务治理功能,实现服务的注册与发现.
Eureka最开始在亚马逊的 AWS 云中使用,通过提供定位服务来进行中间层服务器的负载均衡和故障转移.
2. Eureka内部架构
Spring Cloud Eureka采用了 C/S 的架构方案,主要由两部分组成: Eureka server和Eureka client,并且服务端与客户端均采用Java编写,所以Eureka主要适用于通过Java实现的分布式系统,或是JVM兼容语言构建的系统. Eureka Server作为服务注册服务器,Eureka Client是一个Java客户端,用来简化与服务器的交互、作为轮询负载均衡器,并提供服务的故障切换支持.
Eureka Server 作为服务注册功能的服务器,可以作为服务的注册中心,负责维护注册的服务列表.而系统中的其他微服务,使用 Eureka Client连接到 Eureka Server,并维持心跳连接. 这样系统的维护人员就可以通过 Eureka Server 来监控系统中各个微服务是否正常运行.Spring Cloud 的一些其他模块(比如Zuul),就可以通过 Eureka Server 来发现系统中的其他微服务,并执行相关的逻辑.
Eureka的服务端提供了较为完善的REST API,所以Eureka也支持将非Java语言实现的服务纳入到Eureka服务治理体系中来,只需要其他语言平台自己实现Eureka的客户端程序. 目前.Net平台的Steeltoe、Node.js的eureka-js-client等都已经实现了各自平台的Eureka客户端组件.
3. Eureka组件
Eureka由多个服务实例组成,这些服务实例可以分为两种:
Eureka Server和Eureka Client(provider+consumer)
一个最简单的微服务架构图:

3.1 Eureka Server
Eureka Server(注册中心):提供服务注册和发现功能,负责维护注册的服务列表,管理各种服务功能,包括服务的注册、发现、熔断、负载、降级等;
3.2 Eureka Client
3.2.1 Service Provider(服务提供方):作为一个Eureka Client,将自身服务注册到Eureka中心,向Eureka Server进行服务注册、续约和下线等操作,注册的主要数据包括服务名、机器ip、端口号、域名等,从而使服务消费方能够找到;
3.2.2 Service Consumer(服务消费方):作为一个Eureka Client,从Eureka注册中心获取注册服务列表,获取Service Provider的注册信息,并通过远程调用与Service Provider进行通信,从而能够消费服务.
4. Eureka服务端特点
Eureka Server节点启动后,会首先尝试从邻近节点获取所有实例的注册表信息,完成初始化.
Eureka服务端,即服务注册中心.它同其他服务注册中心一样,支持高可用配置.依托于强一致性提供良好的服务实例可用性,可以应对多种不同的故障场景.
Eureka服务端支持集群模式部署,当集群中有分片发生故障的时候,Eureka会自动转入自我保护模式.它允许在分片发生故障的时候继续提供服务的注册和发现,当故障分片恢复时,集群中的其他分片会把他们的状态再次同步回来.集群中的不同服务注册中心通过异步模式互相复制各自的状态,这也意味着在给定的时间点每个实例关于所有服务的状态可能存在不一致的现象.
5. Eureka客户端特点
Eureka客户端,主要用来处理服务的注册和发现.客户端服务通过注册和参数配置的方式,嵌入在客户端应用程序的代码中.在应用程序启动时,Eureka客户端向服务注册中心注册自身提供的服务,并周期性的发送心跳来更新它的服务租约.同时,它也能从服务端查询当前注册的服务信息并把它们缓存到本地并周期性的刷新服务状态.
- 服务注册: 启动时,会调用服务注册方法,向Eureka Server注册自己的信息. Eureka Server会维护一个已注册的服务列表.当实例状态发生变化时(如自身检测认为Down的时候),也会向Eureka Server更新自己的服务状态,同时用replicateToPeers()方法向其它Eureka Server节点做状态同步.
- 续约与剔除: 服务实例启动后,会周期性地向Eureka Server发送心跳以续约自己的信息,避免自己的注册信息被剔除. 续约的方式与服务注册基本一致,首先更新自身状态,再同步到其它Peer. 如果Eureka Server在一段时间内没有接收到某个微服务节点的心跳,Eureka Server将会注销该微服务节点(自我保护模式除外).
- 服务消费: Service Consumer本质上也是一个Eureka Client. 它启动后,会从Eureka Server上获取所有实例的注册信息,包括IP地址、端口等,并缓存到本地.这些信息默认每30秒更新一次.而服务的消费方如果与Eureka Server通信中断,Service Consumer仍然可以通过本地缓存与Service Provider通信.
6. 为什么选择Eureka?
- 1️⃣. Eureka完全开源,是Netflix公司的开源产品,经历了Netflix公司的生产环境的考验,以及多年时间的不断选代,在功能和性能上都非常稳定,可以放心使用;
- 2️⃣. Eureka是Spring Cloud首选推荐的服务注册与发现组件,与Spring Cloud其他组件可以无疑对接;
- 3️⃣. Eureka和其他组件,比如负载均衡组件Ribbon、熔断器组件Hystrix、熔断器监控组件Hystrix Dashboard组件、熔断器聚合监控Turbine组件,以及网关Zuul组件相互配合,能够很容易实现服务注册、负载均衡、熔断和智能路由等功能.这些组件都是由Netflix公司开源的,一起被称为Netflix OSS组件.Netflix OSS组件由Spring Cloud整合为Spring Cloud Netflix组件,它是Spring Cloud的构架微服务的核心组件,也是基础组件.
7. Eureka的功能
Eureka是Spring Cloud生态下的服务注册中心组件,类似功能的常用组件还有zookeeper, consul等, 在spring cloud中, eureka提供如下功能的服务.
1️⃣. 服务注册
微服务架构中的服务提供者也是Eureka客户端,在其启动的时候,
会向Eureka服务器注册自己的服务信息,同时Eureka服务器会
维护一个注册的服务列表.
2️⃣. 服务发现
服务发现有两种模式,一种是客户端发现模式,一种是服务端发现模式.
Eureka采用的是客户端发现模式.
Eureka Client需要每隔30秒给Eureka Server发送一次心跳,
同时更新Server上最新的注册信息到本地.
并且每次返回注册列表信息可能不同,由Eureka客户端自动处理.
如果Server多次没有收到来自客户端的心跳,那么在90秒内会被Server上剔除.
3️⃣. 服务续约
当注册成功后,eureka客户端会以每隔30秒(可配置)的频率向Eureka服务器发送一次心跳.
发送心跳其实就是执行服务续约操作,避免自己的注册信息被Eureka服务器删除,
续约处理和服务注册基本一致.
4️⃣. 服务下线
当服务实例关闭时,会先向Eureka服务器发送服务下线申请,
Eureka服务器会将该实例从注册表中删除.
注意:
SpringCloud中实现服务的注册和发现功能的组件,包括Eureka/Consul/Zookeeper等,其中Eureka 是Spring Cloud首选推荐的服务注册与发现组件.
虽然Eureka 2.0的开源工作宣告停止,但是不管后期Eureka 如何发展,它对Spring Cloud的影响都不是很大,毕竟还有Consul/Zookeeper等可以选择.
二. Eureka的服务治理体系
1. Eureka服务治理概念
服务治理是微服务架构的核心和基础,主要的功能是提供服务的注册和发现.
简单理解就是服务把自己的访问信息告诉注册中心,在服务调用时,服务消费者不需要真正知道服务提供者实际地址(IP),而是通过服务提供者的服务名去调用,理论上可以无限横向扩展.
比如说在Http或WebService请求的时候,URL地址必须是域名或者是IP地址,而现在只需要知道服务名即可,不需要关注提供者的实际地址.服务提供者的实际地址对消费者而言是透明的,这样有一个很明显的好处:无论提供者是切换网络修改了IP或者是新增了服务器配置,消费者都无须知道,也不需要做任何改动.
由于Spring Cloud为服务治理做了一层抽象接口,所以在Spring Cloud应用中可以支持多种不同的服务治理框架,比如: Netflix Eureka、Consul、Zookeeper.在Spring Cloud服务治理抽象层的作用下,我们可以无缝地切换服务治理实现,并且不影响任何其他的服务注册、服务发现、服务调用等逻辑.
所以Eureka组件可以很好的承担SpringCloud中的服务治理功能.
2. Eureka服务治理的原理

从图中可以看到,Eureka分为两部分.一个是Eureka Server作为注册中心,一般在生产环境上我们会搭建多个注册中心以实现高可用.每个服务单元向注册中心登记自己提供的服务,包括服务的主机与端口号、服务版本号、通讯协议等一些附加信息.注册中心按照服务名分类组织服务清单,同时还需要以心跳检测的方式去监测清单中的服务是否可用,若不可用需要从服务清单中剔除,以达到排除故障服务的效果.
另一个是Eureka Client,它嵌入在客户端应用代码里,当应用启动时,向注册中心注册自己提供的服务,并周期性的发送心跳来更新它的服务租约.同时,它也能从服务端查询当前注册的服务信息并把它们缓存到本地并周期性的刷新服务状态.

三. Eureka中的一些概念
1. Register: 服务注册
当Eureka Client向Eureka Server注册时,它提供自身的元数据,比如IP地址、端口等.
2. Renew: 服务续约
Eureka client每隔30秒发送一次心跳来续约,通过续约来告知Eureka Server该Eureka Client仍然是存活的状态. 正常情况下,如果Eureka Server在90秒没有收到Eureka Client的续约,它会将实例从其注册表中删除,建议不要更改续约间隔.
3. Fetch Registries: 获取注册列表信息
Eureka Client从Eureka server中获取注册列表信息,并将其缓存在本地.客户端会使用该信息查找其他服务,从而进行远程调用.该注册列表信息定期(每30秒钟)更新一次,每次返回的注册列表信息可能与Eureka客 Client的缓存信息不同,此时Eureka Client会自动处理.如果由于某种原因导致客户端的注册服务列表信息和服务端最新的服务注册列表信息不能及时匹配,Eureka Client 则会重新获取整个注册表信息. Eureka Client进行缓存服务列表信息的时候,会将整个的注册服务列表以及每个应用程序的信息进行压缩,压缩的内容和没有压缩的内容完全相同.
Eureka Client 和Eureka server可以使用JSON / XML格式进行通讯,在默认的情况下Eureka客户端使用压缩JSON格式来获取注册列表的信息.
4. Cancel: 服务下线
Eureka Client 在程序关闭时向Eureka server发送取消请求.发送请求后,该客户端实例信息将从服务器的实例注册表中删除,它需要调用以下内容:
DiscoveryManager.getInstance().shutdownComponent();
5. Eviction: 服务剔除
在默认的情况下,当Eureka客户端连续90秒没有向Eureka服务器发送服务续约,即心跳,Eureka服务器会将该服务实例从服务注册列表删除,即服务剔除.
四. Eureka的数据复制方式
一般而言,分布式系统数据在多个副本间的复制方式,可分为主从复制和对等复制.
主从复制: 也就是Master-Slave模式,有一个主副本,其他的为从副本,所有对数据的写操作都要提交到主副本,然后再由主副本更新到其他副本,更新方式分为同步更新、异步更新、同步异步混合更新.
由于写操作都在主副本上,所以它是整个系统的瓶颈,读操作可以分担到从副本上.
对等复制: Peer to Peer模式,副本间部分主从,任何副本都可以接受读写操作,然后相互更新.各个副本之间的同步及冲突处理是个比较棘手的问题,Eureka采用的就是这种方式.
五. Eureka的自我保护机制
1. 自我保护机制的概念
默认情况下,如果Eureka Server在一定时间内(默认90秒),没有接收到某个微服务实例的心跳,Eureka Server将会移除该实例.但是当网络分区故障发生时,微服务与Eureka Server之间无法正常通信,而微服务本身是正常运行的,此时不应该移除这个微服务,所以引入了自我保护机制.
自我保护的工作机制是如果在15分钟内超过85%的客户端节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,Eureka Server自动进入自我保护机制,此时会出现以下几种情况:
- 1️⃣.Eureka Server不再从注册列表中移除因为长时间没收到心跳而应该过期的服务;
- 2️⃣.Eureka Server仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上,保证当前节点依然可用;
- 3️⃣.当网络稳定时,当前Eureka Server中新的注册信息会被同步到其它节点中.
2. 自我保护机制的重要参数
关于自我保护有几个重要参数,renews和threshold.
eureka默认心跳周期30s,即一分钟两次.
Renews(last min):过去一分钟Eureka Server收到的心跳数目;
threshold: 心跳次数的阈值;
RenewalPercentThreshold: 保护机制触发阈值,默认0.85.
比如我们开启了一个eureka server和一个client,eureka server的最小threashold是1(写死在eureka代码中),另一个client在一分钟发两次心跳,那么threshold=1+2*1.
如果Renews < threashold * RenewalPercentThreshold
则触发保护机制,不会移除服务,并报出错误,2 < 0.85*3,因此报错.
3. 解决办法
注意,不建议在生存环境使用,了解即可.
3.1 修改配置,使触发条件不成立
比如修改心跳时间加入以下配置:
instance:
lease-renewal-interval-in-seconds: 1
lease-expiration-duration-in-seconds: 2
leaseRenewalIntervalInSeconds: 30 #Eureka客户端向服务端发送心跳的时间间隔,单位为秒,默认是30秒.
leaseExpirationDurationInSeconds: 90 #Eureka服务端在收到最后一次心跳之后等待的时间上限,单位为秒.超过该时间之后服务端会将该服务实例从服务清单中剔除,从而禁止服务调用请求被发送到该实例上,默认是90秒
RenewalPercentThreshold: 0.85
#threshold=1 + 60 * 1 =61
#60 > 61 * 0.85 所以不会触发自我保护机制
#或者把RenewalPercentThreshold的值调低,比如0.49
3.2 测试及生产环境直接关闭自我保护机制
eureka:
server:
enable-self-preservation: false
六. Eureka与Zookeeper对比

1. CAP理论
在总结两者的区别之前,我们先来回顾一下 CAP 理论. CAP 理论是由 Eric Brewer 教授提出的作用于分布式系统中的一个重要的概念. 具体如下:
- C(Consistency): 数据一致性. 大家都知道,在分布式系统中,数据会有副本. 由于网络或者机器故障等因素,可能有些副本数据写入正确,有些却写入错误或者失败,这样就导致了数据的不一致了,而要满足数据的一致性规则,就是保证所有数据都要同步;
- A(Availability): 可用性. 我们需要获取什么数据时,都能够正常的获取到想要的数据(当然,允许可接受范围内的网络延迟),也就是说,要保证任何时候请求数据都能够正常响应;
- P(Partition Tolerance): 分区容错性. 当网络通信发生故障时,集群仍然可用,不会因为某个节点挂了或者存在问题,而影响整个系统的正常运作. 对于分布式系统来说,出现网络分区是不可避免的,因此分区容错性是必须要具备的. 也就是说,CAP理论中,P是必然的,是个客观存在的事实,不可避免,也无法绕过.
2. Zookeeper的CP原则
对于 Zookeeper 来书,它是满足 CP 原则的,也就是说,Zookeeper 是保证数据的一致性的. 但是这里还需要注意一点是,Zookeeper 它并不是强一致的. 什么意思呢? 打个比方,现在客户端 A 提交一个写操作,Zookeeper 在过半数节点操作成功之后就可以返回.但此时客户端 B 读操作请求的是 A 写操作尚未同步到的节点,那么读取的就不是 A 最新提交的数据了.
那如何保证强一致性呢?我们可以在读取数据的时候先执行一下sync 操作,即与 leader 节点先同步一下数据,再去读取,这样才能保证数据的强一致性.
但是 Zookeeper 也有个缺陷,刚刚提到了 leader 节点,当 master 节点因为网络故障与其他节点失去联系时,剩余节点会重新进行 leader 选举.问题在于,选举 leader 的时间太长,30 ~ 120s,且选举期间整个 Zookeeper 集群都是不可用的,这就导致在选举期间注册服务瘫痪.
在云部署的环境下,因网络问题使得 Zookeeper 集群失去 master 节点是比较大概率会发生的事,虽然服务能够最终恢复,但是漫长的选举时间导致的注册长期不可用是不能容忍的,比如双十一当天,那就是灾难性的.
3. Eureka的AP原则
大规模网络部署时,失败是在所难免的,因此我们无法回避这个问题.当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的注册信息,但不能接受服务直接 down 掉不可用.
Eureka 在被设计的时候,就考虑到了这一点,因此在设计时优先保证可用性,这就是 AP 原则.Eureka 各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务.而 Eureka 的客户端在向某个 Eureka Server 注册时如果发现连接失败,则会自动切换至其它节点,只要有一台 Eureka 还在,就能保证注册服务可用(即保证A原则),只不过查到的信息可能不是最新的(不保证B原则).
正因为应用实例的注册信息在集群的所有节点间并不是强一致的,所以需要客户端能够支持负载均衡以及失败重试.在 Netflix 的生态中,ribbon 可以提供这个功能.
因此,Eureka 可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像 Zookeeper 那样使整个注册服务瘫痪.
作为服务注册中心,最重要的是要保证可用性,可以接受短时间内数据不一致的情况. 个人觉得 Eureka 作为单纯的服务注册中心来说要比 Zookeeper 更加“专业”一点.
4. 服务注册发现方式
Eureka和Zookeeper使用客户端发现方式,Consul属于服务端发现方式.
标签:服务,04,SpringCloud,Server,注册,Eureka,节点,客户端 From: https://blog.51cto.com/u_7044146/5965886