一、概述
Eureka2.0版本已经停止维护,为什么要写这篇博客重复已停止更新的中间件,其目的主要是:
- 认识微服务注册中心:虽然Eureka已经停止维护,但微服务架构在当今非常流程,学习Eureka可以更好的理解微服务。
- 便于老旧系统维护:如果使用微服务,公司一定会存在使用Eureka服务的应用系统,学习Eureka便于储备老旧系统维护的能力。
二、Eureka简介
Eureka是Netflix的一个子模块,也是核心模块之一。Eureka是一个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移。
三、Eureka结构与作用
Eureka结构图
Eureka采用CS(Client/Server,客户端/服务器)架构,它包括以下两大组件
- Eureka Server:Eureka 服务注册中心,主要用于提供服务注册功能。当微服务启动时,会将自己的服务注册到 Eureka Server。Eureka Server 维护了一个可用服务列表,存储了所有注册到 Eureka Server 的可用服务的信息,这些可用服务可以在 Eureka Server 的管理界面中直观看到。
- Eureka Client:Eureka 客户端,通常指的是微服务系统中各个微服务,主要用于和 Eureka Server 进行交互。在微服务应用启动后,Eureka Client 会向 Eureka Server 发送心跳(默认周期为 30 秒)。若 Eureka Server 在多个心跳周期内没有接收到某个 Eureka Client 的心跳,Eureka Server 将它从可用服务列表中移除(默认 90 秒)。
"心跳"是一段定时发送的自定义信息,让对方知道自己"存活",以确保连接有效性,大部分CS架构的应用程序都采用心跳机制,服务端和客户端都可以发送心跳。通常情况下客户端发送请求心跳包给服务器端。服务器端判断客户端是否存活在线。
四、Eureka集群及与应用关系
- Eureka 实现服务注册与发现的流程
- 服务提供者(Eureka Client Provider)启动时,把当前服务器信息以服务名(spring.application.name)的方式注册到注册中心。
- 服务器消费者(Eureka Client Consumer)启动时,也会注册自己的服务名到注册中心。
- 服务消费者(Consumer)注册的同时会获取一份可用的服务器列表。该列表中包含了所有注册到服务注册中心的服务信息(包含服务器提供者和自身服务信息)。
- 在获得可用服务列表后,服务消费者通过HTTP或消息中间件远程调用服务者提供服务。
服务中心(Eureka Server)是个十分重要的角色,他是服务提供者(Provider)和服务消费者(Consumer)之间的桥梁。服务提供者只有将自己的服务注册到服务注册中心才可能被服务消费者调用。而服务消费者也只有通过服务注册中心获取可用服务列表后,才能调用所需的服务。为保证应用的高可用型;使用多个注册中心,相互注册保证任何一台注册中心故障不影响整个服务器中心向外提供服务。
五、Eureka注册中心实现
- pom.xml添加依赖
1.添加spring-boot-starter-parent依赖
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.6.RELEASE</version> <relativePath/> </parent>
2.添加依赖dependencyManagement
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Hoxton.SR12</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
3.添加相关依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <version>3.0.5</version> <scope>test</scope> </dependency>
package com.goyeer; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; //Eureka注册中心注解 @EnableEurekaServer @SpringBootApplication public class EurekaService { public static void main(String[] args){ SpringApplication.run(EurekaService.class,args); } }
server: port: 30009 eureka: instance: #服务注册中心实例的主机名 hostname: localhost client: #实例是否在eureka服务器上注册自己的信息以供其他服务发现,默认为true register-with-eureka: false #此客户端是否获取eureka服务器注册表上的注册信息,默认为true fetch-registry: false service-url: #与Eureka注册服务中心的通信zone和url地址 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ registerWithEureka: false fetchRegistry: false server: enable-self-preservation: false eviction-interval-timer-in-ms: 500
六、Eureka客户端
- pom.xml添加依赖
pom文件可用直接使用Eureka服务端pom文件,只需要把spring-cloud-starter-netflix-eureka-server替换为spring-cloud-netflix-eureka-client
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-netflix-eureka-client</artifactId> </dependency>
package com.awinic; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @EnableEurekaClient @SpringBootApplication public class EurekaProviderClientApp { public static void main(String[] args){ SpringApplication.run(EurekaProviderClientApp.class,args); } }
server: port: 30001 eureka: instance: hostname: localhost client: #实例是否在eureka服务器上注册自己的信息以供其他服务发现,默认为true register-with-eureka: true fetch-registry: false service-url: defaultZone: http://${eureka.instance.hostname}:30000/eureka/ registerWithEureka: false fetchRegistry: false
七、自我保护机制
Eureka在CAP理论当中是属于AP , 也就说当产生网络分区时,Eureka保证系统的可用性,但不保证系统里面数据的一致性,当发生网络分区的时候,Eureka-Server和Client端的通讯被终止,Eureka Server端接收不到Eureka Client续约请求,此时,如果直接将没有收到心跳Eureka Client端自动剔除,那么就可能误把正常的Eureka Client端给剔除。这个不符合AP理论,所有Eureka-Server会保留可能已宕机的Eureka Server端。从而保证了Eureka Server的健壮性,符合AP理论。
Eureka重要两个变量:
this.expectedNumberOfRenewsPerMin = count * 2; this.numberOfRenewsPerMinThreshold =(int) (this.expectedNumberOfRenewsPerMin * serverConfig.getRenewalPercentThreshold());
expectedNumberOfRenewsPerMin :每分钟最大的续约数量,由于客户端是每30秒续约一次,一分钟就是续约2次, count代表的是客户端数量。
所以这个变量的计算公式 : 客户端数量*2
numberOfRenewsPerMinThreshold : 每分钟最小续约数量, 使用expectedNumberOfRenewsPerMin * serverConfig.getRenewalPercentThreshold()。
serverConfig.getRenewalPercentThreshold()的默认值为0.85 , 也就是说每分钟的续约数量要大于85% 。
Eureka的自我保护机制,都是围绕以上两个变量实现的,如果每分钟的续约数量小于numberOfRenewsPerMinThreshold,此时就会开启自动保护机制。
在此期间,Eureka Server不会主动剔除任何一个客户端。
八、总结
Eureka 是Spring Cloud核心它提供一下几个主要的服务:
- 服务注册和发现:eureka 分客户端(Eureka Client)和服务端(Eureka Server),服务端即为注册中心,提供服务注册和发现的功能。所有客户端将自己注册到注册中心上,服务端使用 Map 结构基于内存保存所有客户端信息(IP、端口、续约等信息)。客户端定时从注册中心拉取注册表到本地,就可以通过负载均衡的方式进行服务间的调用。
- 服务注册(Register):Eureka Client 启动时向 Eureka Server 注册,并提供自身的元数据、IP地址、端口、状态等信息。
- 服务续约(Renew):Eureka Client 默认每隔
30秒
向 Eureka Server 发送一次心跳进行服务续约,通过续约告知 Eureka Server 自己是正常的。如果 Eureka Server180秒
没有收到客户端的续约,就会认为客户端故障,并将其剔除。 - 抓取注册表(Fetch Registry):Eureka Client 启动时会向 Eureka Server 全量抓取一次注册表到本地,之后会每隔
30秒
增量抓取注册表合并到本地注册表。如果合并后的本地注册表与 Eureka Server 端的注册表不一致(hash 比对),就全量抓取注册表覆盖本地的注册表。 - 服务下线(Cancel):Eureka Client 程序正常关闭时,会向 Eureka Server 发送下线请求,之后 Eureka Server 将这个实例从注册表中剔除。
- 故障剔除(Eviction):默认情况下,Eureka Client 连续
180秒
没有向 Eureka Server 发送续约请求,就会被认为实例故障,然后从注册表剔除。 - Eureka Server 集群:Eureka Server 采用对等复制模式(
Peer to Peer
)来进行副本之间的数据同步,集群中每个 Server 节点都可以接收写操作和读操作。Server 节点接收到写操作后(注册、续约、下线、状态更新)会通过后台任务打包成批量任务发送到集群其它 Server 节点进行数据同步。Eureka Server 集群副本之间的数据会有短暂的不一致性,它是满足 CAP 中的 AP,即 高可用性和分区容错性
。
后面将陆续介绍Eureka配置项、Eureka服务集群、Eureka源码解析…