1 Eureka简介
Eureka是Netflix的一个子模块,也是核心模块之一。 Eureka是一项基于REST(代表性状态转移)的服务。主要在AWS云中用于查找服务,以实现负载均衡和中间层服务器的故障转移。 SpringCloud将它集成在其子项目spring-cloud-netflix中,以实现SpringCloud的服务发现功能。服务注册与发现对于微服务架构来说是非常重要的,有了服务发现于注册,只需要使用服务的标识符, 就可以访问到服务,而不需要修改服务的配置文件了。功能类似于Dubbo的注册中心,比如Zookeeper。
2 Eureka基本组件
Eureka包含两个组件:Eureka Server和Eureka Client。
Eureka Server提供服务注册服务,各个节点启动后,会在Eureka Server中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。
@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
server:
port: 8899
eureka:
instance:
hostname: localhost #Eureka服务端实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己(自己就是注册中心)
fetch-registry: false #false 不检索服务列表(注册中心自身不需要检测服务列表)
serviceUrl: #设置与Eureka Server 交互的地址 查询服务和注册服务都需要依赖这个地址
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
spring:
application:
name: eureka-server
Eureka Client是一个java客户端,用于简化与Eureka Server的交互,客户端同时也就是一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳,默认周期为30秒,如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,Eureka Server将会从服务注册表中把这个服务节点移除(默认90秒)。
@SpringBootApplication
@EnableEurekaClient
public class EurekaProviderApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaProviderApplication.class, args);
}
}
server:
port: 8898
spring:
application:
name: eureka-provider
eureka:
instance:
hostname: euraka-provider
lease-expiration-duration-in-seconds: 90 #没有心跳的淘汰时间,即服务续约到期时间(缺省90s)
lease-renewal-interval-in-seconds: 30 #心跳时间,即服务续约间隔时间(缺省30s)
client:
serviceUrl:
defaultZone: http://localhost:8899/eureka/
Eureka Server之间通过复制的方式完成数据的同步,Eureka还提供了客户端缓存机制,即使所有的Eureka Server都挂掉,客户端依然可以利用缓存中的信息消费其他服务的API。综上,Eureka通过心跳检查、客户端缓存等机制,确保了系统的高可用性、灵活性和可伸缩性。
Spring Cloud封装了Netflix公司开发的Eureka模块来实现服务注册和发现(请对比Zookeeper)
Eureka采用了C–S的设计架构。Eureka Server作为服务注册功能的服务器,它是服务注册中心。
而系统中的其他微服务,使用Eureka的客户端连接到Eureka Server 并维持心跳连接,这样系统的维护人员就可以通过Eureka Server 来监控系统中各个微服务是否正常运行。Spring Cloud的一些其他模块(比如Zuul)就可以通过Eureka Server来发现系统中的其他微服务,并执行相关的逻辑。
注册中心服务端主要对外提供了三个功能:
服务注册
服务提供者启动时,会通过 Eureka Client 向 Eureka Server 注册信息,Eureka Server 会存储该服务的信息,Eureka Server 内部有二层缓存机制来维护整个注册表
提供注册表
服务消费者在调用服务时,如果 Eureka Client 没有缓存注册表的话,会从 Eureka Server 获取最新的注册表
同步状态
Eureka Client 通过注册、心跳机制和 Eureka Server 同步当前客户端的状态。
Register: 服务注册
服务的提供者,将自身注册到注册中心,服务提供者也是一个 Eureka Client。当 Eureka Client 向 Eureka Server 注册时,它提供自身的元数据,比如 IP 地址、端口,运行状况指示符 URL,主页等。
Renew: 服务续约
Eureka Client 会每隔 30 秒发送一次心跳来续约。 通过续约来告知 Eureka Server 该 Eureka Client 运行正常,没有出现问题。 默认情况下,如果 Eureka Server 在 90 秒内没有收到 Eureka Client 的续约,Server 端会将实例从其注册表中删除,此时间可配置,一般情况不建议更改。
服务续约的两个重要属性
服务续约任务的调用间隔时间,默认为30秒
eureka.instance.lease-renewal-interval-in-seconds=30
服务失效的时间,默认为90秒。
eureka.instance.lease-expiration-duration-in-seconds=90
Eviction 服务剔除
当 Eureka Client 和 Eureka Server 不再有心跳时,Eureka Server 会将该服务实例从服务注册列表中删除,即服务剔除。
Cancel: 服务下线
Eureka Client 在程序关闭时向 Eureka Server 发送取消请求。 发送请求后,该客户端实例信息将从 Eureka Server 的实例注册表中删除。该下线请求不会自动完成,它需要调用以下内容:
DiscoveryManager.getInstance().shutdownComponent();
GetRegisty: 获取注册列表信息
Eureka Client 从服务器获取注册表信息,并将其缓存在本地。客户端会使用该信息查找其他服务,从而进行远程调用。该注册列表信息定期(每30秒钟)更新一次。每次返回注册列表信息可能与 Eureka Client 的缓存信息不同,Eureka Client 自动处理。
如果由于某种原因导致注册列表信息不能及时匹配,Eureka Client 则会重新获取整个注册表信息。 Eureka Server 缓存注册列表信息,整个注册表以及每个应用程序的信息进行了压缩,压缩内容和没有压缩的内容完全相同。Eureka Client 和 Eureka Server 可以使用 JSON/XML 格式进行通讯。在默认情况下 Eureka Client 使用压缩 JSON 格式来获取注册列表的信息。
获取服务是服务消费者的基础,所以必有两个重要参数需要注意:
# 启用服务消费者从注册中心拉取服务列表的功能
eureka.client.fetch-registry=true
# 设置服务消费者从注册中心拉取服务列表的间隔
eureka.client.registry-fetch-interval-seconds=30
Remote Call: 远程调用
当 Eureka Client 从注册中心获取到服务提供者信息后,就可以通过 Http 请求调用对应的服务;服务提供者有多个时,Eureka Client 客户端会通过 Ribbon 自动进行负载均衡。
3.三大角色
Eureka Server : 提供服务注册和发现
Service Consumer:服务消费方从eurake或许注册服务列表,从而能能够消费服务
Service Provider:服务提供方将自身服务注册到eureka,从而使服务消费方能够找到
4.自我保护
自我保护机制:
某时刻某一个微服务不可用了,eureka不会立刻清理,依旧会对该微服务的信息进行保存
默认情况下,如果eureka server 在一定时间内没有接收到某个微服务实例的心跳,eureka server将会注销该实例(lease-expiration-duration-in-seconds 属性,默认90s)
但是当网络分区故障发生时,微服务客户端与eureka server之间无法正常通信,以上行为可能变得非常危险了,因为微服务本身其实是健康的,此时不应该注销这个微服务,eureka 通过自我保护模式来解决这个问题。当eureka server 节点在短时间内丢失过多的客户端时,可能发生了网络分区故障,那么这个节点就会进入自我保护模式,一旦进入该模式,eureka server 就会保护服务注册表中的信息,不再删除服务注册表中的数据(也就是不会注销任何微服务),当网络故障恢复后,该eureka server 节点会自动退出自我保护模式。
在自我保护模式中,eurak server 会保护服务注册表中的信息,不再注销任何服务实例。当它收到的心跳数重新恢复到阈值以上时,该eureka server 节点就会自动退出自我保护模式。它的设计哲学就是宁可保留错误的服务注册信息,也不盲目注销任何可能健康的服务实例。
Eurka 工作流程
1、Eureka Server 启动成功,等待服务端注册。在启动过程中如果配置了集群,集群之间定时通过 Replicate 同步注册表,每个 Eureka Server 都存在独立完整的服务注册表信息
2、Eureka Client 启动时根据配置的 Eureka Server 地址去注册中心注册服务
3、Eureka Client 会每 30s 向 Eureka Server 发送一次心跳请求,证明客户端服务正常
4、当 Eureka Server 90s 内没有收到 Eureka Client 的心跳,注册中心则认为该节点失效,会注销该实例
5、单位时间内 Eureka Server 统计到有大量的 Eureka Client 没有上送心跳,则认为可能为网络异常,进入自我保护机制,不再剔除没有上送心跳的客户端
6、当 Eureka Client 心跳请求恢复正常之后,Eureka Server 自动退出自我保护模式
7、Eureka Client 定时全量或者增量从注册中心获取服务注册表,并且将获取到的信息缓存到本地
8、服务调用时,Eureka Client 会先从本地缓存找寻调取的服务。如果获取不到,先从注册中心刷新注册表,再同步到本地缓存
9、Eureka Client 获取到目标服务器信息,发起服务调用
10、Eureka Client 程序关闭时向 Eureka Server 发送取消请求,Eureka Server 将实例从注册表中删除
这就是Eurka基本工作流程
复习一下:
CAP理论
C - consistency 强一致性
A - availability 可用性
P - partition tolerance 分区容错性
CAP核心理论
一个分布式系统不可能同时很好的满足一致性,可用性,和分区容错性三个需求
因此根据CAP原则讲nosql 数据库分成了满足CA原则,满足CP原则 和满足 AP原则三大类
CA - 单点集群,满足一致性,可用性,通常在可拓展性上不太强大
CP - 满足一致性,分区容错性的系统,通常性能不是特别的高
AP - 满足可用性,分区容错性,通过对数据一致性要求低一些。
所以,分布式系统考虑到集群的拓展,只能选择CP 或者 AP 。
CAP的3进2
CAP理论就是说再分布式存储系统中,最多只能实现上面两点。而由于当前的网络硬件肯定会出现延迟丢包的问题,所以分区容错性是我们必须实现的
所以我们只能在一致性和可用性之间进行权衡,没有NOSQL系统能同时保证这三点。
CA:传统的Oracle数据库
AP:大多数网站的架构选择,Eureka
CP:Redis,Mongdb
作为服务注册中心,Eureka比Zookeeper好在哪里?
Zookeeper 保证CP
当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的注册信息,但不能接受服务直接down掉不可用,也就是说,服务注册功能对可用性的要求高于一致性。
但是zk会出现这样一种情况,当master节点因为网络故障与其他节点失去联系时,剩余节点回重新进行leader选举,问题在于选举leader的时间太长,30~120s且选举期间整个zk集群都是不可用的。这就导致在选举期间注册服务瘫痪,在云部署的环境下,因网络问题使得zk集群失去master节点很大概率会发生的事情。虽然服务能够最终恢复,但是漫长的选举时间导致的注册长期不可用时不能容忍的。
Eureka 保证AP
eureka 看明白了这一点,因此在设计时就先保证可用性。Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而eureka客户端再向某个eureka服务端注册时如果发现连接失败,则会自动切换至其他节点。只要有一台eureka server 是ok的,就能保证服务可用(保证服务可用)。只不过查询到的信息可能不是最新的(不保证强一致性)。除此之外,eureka还有一种自我保护机制,上篇中也?说。如果在15分钟内超过85%的节点都没有正常的心跳,那么eureka就认为客户端与注册中心出现了网络故障,此时会出现如下几种情况:
- eureka 不再从注册列表中移除因为长时间没收到心跳而应该过期的服务。
- eureka 仍然能够接受新服务的注册和查询请求,但是不会被同步到其他节点上(即保证当前节点依然可用)
- 当网络稳定时,当前实例新的注册信息会被同步到其他节点中,因此,eureka可以很好的应对网络故障导致部分节点失去联系的情况而不会像zk那样使整个注册服务瘫痪。
因此,Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像Zookeeper那样使整个注册服务瘫痪。