服务注册与发现 - Eureka
在不使用服务注册的前提下,如果在微服务中需要服务间调用,只能使用 RestTemplate 指定主机ip及端口号port才能进行通讯。但是这样的硬编码编写提供方地址的方式会出现如下问题:**(1)如果服务提供者的网络地址发生了变化,会影响消费者;(2)在生产环境中,每个微服务都会有多个实例来实现容灾和负载均衡,而使用硬编码的形式无法适应这种需求。**由于以上两个问题,所以出现了服务发现组件。
服务提供者、服务消费者、服务发现组件关系:
- 各个微服务在启动时,将自己的网络地址等信息注册到服务发现组件中,服务发现组件会存储这些消息;
- 服务消费者可以从服务发现组件查询服务提供者的网络地址,并使用该地址 调用服务提供者的接口;
- 各个微服务与服务发现组件使用一定机制(例如心跳)通信。服务发现组件若长时间无法与某微服务实例通信,就会注销该实例并剔除;
- 微服务网络地址发生变更时,会重新注册到服务发现组件。
本文以Eureka为主讲解服务注册与发现。
3.1、Eureka简介
Eureka是Netflix开源的服务发现组件,本身是个基于REST的服务,包含了Server和Client两部分。Netflix是一家在线影片租赁提供商(《谁是被害者》出自于Netflix之手)。官方文档详见Spring Cloud Netflix。
Eureka的GitHub为:GitHub
3.2、Region和Zone:区域与可用区
Eureka 提供了 Region
和 Zone
两个概念来进行分区,这两个概念均来自于亚马逊的 AWS:
其中,Region
表示AWS中的地理位置,每个Region
都有多个Availability Zone
,各个Region
之间完全隔离。
SpringCloud 中的Eureka默认使用的Region
为us-east-1。
# EurekaClientConfigBean.java
eureka.client.region=us-east-1
3.3、Eureka架构图
- Application Service :是一个Eureka Client ,扮演服务提供者的角色,提供业务服务,向 Eureka Server 注册和更新自己的信息,同时能从 Eureka Server 注册表中获取到其他服务的信息。
- Eureka Server :扮演服务注册中心的角色,提供服务注册和发现的功能。每个Eureka Client向 Eureka Server 注册自己的信息,也可以通过 Eureka Server 获取到其他服务的信息达到发现和调用其他服务的目的。
- Application Client :是一个 Eureka Client ,扮演了服务消费者的角色,通过 Eureka Server 获取注册到其上其他服务的信息,从而根据信息找到所需的服务发起远程调用。
- Replicate : Eureka Server 同时也是 Eureka Client,多个Eureka Server实例相互之间通过复制的方式来实现服务注册表中数据的同步,使 Eureka Server 集群中不同注册表中服务实例信息保持一致。
- Make Remote Call :微服务之间的远程调用。
- Register:注册服务实例, Eureka Client 端向 Eureka Server端注册自身的元数据以供服务发现。
- Renew :续约,Eureka Client会周期性(默认30s)通过发送心跳到 Eureka Server 以维持和更新注册表中服务实例元数据的有效性。当在一定时长内(默认90s),Eureka Server没有收到 Eureka Client的心跳信息,将默认服务下线,会把服务实例的信息从注册表中删除。
- Cancel :服务下线, Eureka Client在关闭时主动向 Eureka Server注销服务实例元数据,这时 Eureka Client的服务实例数据将从 Eureka Server的注册表中删除。
- Get Registry :获取注册表, Eureka Client向 Eureka Server请求注册表信息,用于服务发现,从而发起服务间远程调用。
- Eureka Client会缓存服务注册表中的信息。首先,微服务无须每次请求都查询 Eureka Server,从而降低了Eureka Server的压力;其次,即使Eureka Server所有节点都宕掉,服务消费者依然可以使用缓存中的信息找到服务提供者并完成调用。
3.4、工作流程
1、Eureka Server 启动成功,等待服务端注册。在启动过程中如果配置了集群,集群之间定时通过 Replicate 同步注册表,每个 Eureka Server 都存在独立完整的服务注册表信息。
2、Eureka Client 启动时根据配置的 Eureka Server 地址去注册中心注册服务。
3、Eureka Client 会每隔 30s (eureka.instance.lease-renewal-interval-in-seconds=30
)向 Eureka Server 发送一次心跳请求,证明客户端服务正常。
4、当 Eureka Server 在90s (eureka.instance.lease-expiration-duration-in-seconds=90
)内没有收到 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 将实例从注册表中删除。
3.5、自我保护机制
“自我保护机制“主要在 Eureka Client 和 Eureka Server 之间存在网络分区的情况下发挥保护作用,在服务器端和客户端都有对应实现。假设在某种特定的情况下(如网络故障),Eureka Client 和 Eureka Server 无法进行通信,此时 Eureka Client 无法向 Eureka Server 发起注册和续约请求, Eureka Server 中就可能因注册表中的服务实例租约出现大量过期而面临被剔除的危险,然而此时的 Eureka Client 可能是处于健康状态的(可接受服务访问),如果直接将注册表中大量过期的服务实例租约剔除显然是不合理的。
Eureka 设计了“自我保护机制”。在 Eureka Server 处,如果出现大量的服务实例过期被剔除的现象,那么该Server节点将进入自我保护模式,保护注册表中的信息不再被剔除,在通讯稳定后再退出该模式;在 Eureka Client 处,如果向 Eureka Server 注册失败,将快速超时并尝试与其他的 Eureka Server 进行通信。“自我保护机制”的设计大大提高了 Eureka 的可用性。
Eureka 自我保护机制的设计理念遵循 CAP 原则中的 AP 原则,维护系统的可用性,而 Zookeeper 和 Consul 则遵循了 CP 原则,如果服务一下线,注册中心会立即将服务下线。