一、Eureka简介
Eureka是Netflix开发的服务发现框架,其是基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的。SpringCloud将它集成在其子项目spring-cloud-netflix中,以实现SpringCloud的服务发现功能。
1、Eureka组件
Eureka 包含: Eureka Server 和 Eureka Client (Producer生产提供者 和Consumer生产消费者)
1.1 Eureka Server
Eureka Server 提供注册服务,微服务内的相关应用服务按注册要求配置后,启动相关应用服务节点后,会在Eureka Server中进行注册,这样Eureka Server内的服务注册表将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的展现。
Eureka Server本身也是一个服务,默认情况下会自动注册到Eureka注册中心。
如果搭建单机版的Eureka Server注册中心,则需要配置取消Eureka Server的自动注册逻辑。
Eureka Server通过Register、Get、Renew 等接口提供服务的注册、发现和心跳检测等服务。
服务注册(Register)
服务提供者启动时,会通过 Eureka Client 向 Eureka Server 注册信息,Eureka Server 会存储该服务的信息:元数据,比如 IP 地址、端口、运行状况指示符 URL、主页等,Eureka Server 内部有二层缓存机制来维护整个注册表。
1.2 Eureka Client
Eureka Client 是Java客户端,用于与Eureka Server的交互,客户端具备内置的、使用轮询(round-robin)负载算法的负载均衡器。
当应用服务启动后,将会向Eureka Server发送心跳,默认周期为30秒,如果Eureka Server在多个(默认90秒/30秒)心跳周期内没有接收到某应用服务节点的心跳,Eureka Server将会从服务注册表内将此应用服务节点移除。
Eureka Client分为两个角色,分别是:Service Provider 和 Service Consumer。
Service Provider 和 Service Consumer 并不是绝对的,因为Provider在提供服务的同时,也可以消费其他Provider提供的服务;Consumer在消费服务的同时,也可以提供对外服务。
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
Cancel: 服务下线
Eureka Client 在服务程序关闭时向 Eureka Server 发送取消请求。 发送请求后,该客户端实例信息将从 Eureka Server 的实例注册表内删除。
服务下线需请求如下接口:
DiscoveryManager.getInstance().shutdownComponent();
GetRegisty: 获取注册列表信息
Eureka Client 从Eureka Server 获取注册表信息,并将其缓存在本地。Eureka Client会使用该注册表信息查找消费其他服务,从而进行远程调用。该注册列表信息定期更新频率1次/30秒。
注意,获取的注册表信息可能与实际的注册表信息不符。
若因某种原因导致注册列表信息不能及时匹配,Eureka Client 则会重新获取整个注册表信息。 Eureka Server 缓存注册列表信息,整个注册表以及每个应用程序的信息进行了压缩,压缩内容和没有压缩的内容完全相同。Eureka Client 和 Eureka Server 可以使用 JSON/XML 格式进行通讯。在默认情况下 Eureka Client 使用压缩 JSON 格式来获取注册列表的信息。
Cancel: 服务下线
Replicate:同步状态
当 Provider 关闭时会向Eureka发送消息,把自己从服务列表中删除。防止 Consumer 调用到不存在的服务。
Make Remote Call:远程调用
当 Eureka Client 从注册中心获取到服务提供者信息后,就可以通过 Http 请求调用对应的服务;服务提供者有多个时,Eureka Client 客户端会通过 Ribbon 自动进行负载均衡,完成服务的远程调用。
1.3 自我保护机制
服务保护模式(自我保护模式):一般情况下,微服务在Eureka上注册后,会每30秒发送心跳包,Eureka通过心跳来判断服务时候健康,同时会定期删除超过90秒没有发送心跳服务。
导致Eureka Server接收不到心跳包的可能:
A:微服务自身的原因;
B:微服务与Eureka之间的网络故障;
通常微服务自身的故障只会导致个别服务出现故障,一般不会出现大面积故障,而网络故障通常会导致Eureka Server在短时间内无法收到大批心跳。
考虑到网络故障情况,Eureka设置了1个阀值,当判断挂掉的服务的数量超过阀值时,Eureka Server认为很大程度是因出现网络故障,将不再删除心跳过期的服务。
这个阀值是多少呢?Eureka Server在运行期间,会统计心跳失败的比例在15分钟内是否低于85%,如果低于85%,Eureka Server则任务是网络故障,不会删除心跳过期服务。
这种服务保护算法叫做Eureka Server的服务保护模式。
这种不删除的,90秒没有心跳的服务,称为无效服务,但是还是保存在服务列表中。如果Consumer到注册中心发现服务,则Eureka Server会将所有好的数据(有效服务数据)和坏的数据(无效服务数据)都返回给Consumer。
通过 Eureka Server 配置参数,开启或者关闭保护机制,生产环境建议打开:
eureka.server.enable-self-preservation=true
1.4 Eurka 工作流程
(1)、Eureka Server 启动成功,等待服务端注册。若启动过程中配置过Cluster,Cluster之间定时通过 Replicate 同步注册表,每个 Eureka Server 都存在独立完整的服务注册表信息;
(2)、Eureka Client 启动时,根据配置的 Eureka Server 地址去注册中心注册服务;
(3)、Eureka Client 会每 30秒 向 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 将实例从注册表中删除。
二、Eureka搭建
2、Eureka Server 搭建
2.1 Eureka Server单节点
配置:build.gradle
plugins {
id 'org.springframework.boot' version '2.4.1'
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
id 'java'
}
group = 'com.boy'
version = '1.0.0'
sourceCompatibility = '1.8'
repositories {
mavenLocal()
mavenCentral()
maven { url 'https://maven.aliyun.com/repository/public/' }
maven { url 'https://maven.aliyun.com/repository/spring/'}
maven { url "https://repo1.maven.org/maven2/" }
maven { url 'https://repo.spring.io/milestone' }
maven { url "https://mvnrepository.com/repos/central/" }
maven { url "http://jcenter.bintray.com" }
maven { url "http://mvn.gt.igexin.com/nexus/content/repositories/releases" }
maven { url "https://plugins.gradle.org/m2/" }
maven { url "https://repo.spring.io/plugins-release/" }
maven { url "https://repo.spring.io/milestone" }
maven { url "https://oss.sonatype.org/content/repositories/releases/" }
maven { url "https://maven.repository.redhat.com/ga/" }
maven { url "https://repository.apache.org/content/repositories/releases/" }
jcenter()
}
ext {
set('springCloudVersion', "2020.0.0")
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
test {
useJUnitPlatform()
}
配置application.yml:
#单节点
server:
port: 7900
#应用名称及验证账号
spring:
application:
name: EUREKA-SERVER
eureka:
instance:
hostname: localhost
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
server:
#关闭自我保护
enable-self-preservation: false
#清理间隔时间
eviction-interval-timer-in-ms: 5000
logging:
level:
root: info
启动类:
package com.boy.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
2.2 Eureka Server两节点搭建
配置application.yml:
# \u4E24\u8282\u70B9\u642D\u5EFA
# \u5E94\u7528\u540D\u79F0
spring:
application:
name: EUREKA-SERVER
logging:
level:
root: debug
---
spring:
profiles: 7901
server:
port: 7901
eureka:
instance:
hostname: eureka.server.one
client:
#\u8BBE\u7F6E\u670D\u52A1\u6CE8\u518C\u4E2D\u5FC3\u7684URL
service-url:
defaultZone: http://eureka.server.two:7902/eureka/,http://eureka.server.one:7901/eureka/
---
spring:
profiles: 7902
server:
port: 7902
eureka:
instance:
hostname: eureka.server.two
client:
#\u8BBE\u7F6E\u670D\u52A1\u6CE8\u518C\u4E2D\u5FC3\u7684URL
service-url:
defaultZone: http://eureka.server.one:7901/eureka/,http://eureka.server.one:7902/eureka/
配置windows hosts文件:
127.0.0.1 eureka.server.one
127.0.0.1 eureka.server.two
127.0.0.1 eureka.server.third
启动类:
package com.boy.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
idea启动配置:
2.3 Eureka Server三节点搭建
# \u4E24\u8282\u70B9\u642D\u5EFA
# \u5E94\u7528\u540D\u79F0
spring:
application:
name: EUREKA-SERVER
logging:
level:
root: debug
server:
servlet:
context-path: /eureka/
---
spring:
profiles: 7901
server:
port: 7901
eureka:
instance:
hostname: eureka.server.one
client:
#\u8BBE\u7F6E\u670D\u52A1\u6CE8\u518C\u4E2D\u5FC3\u7684URL
service-url:
defaultZone: http://eureka.server.two:7902/eureka/,http://eureka.server.third:7903/eureka/,http://eureka.server.one:7901/eureka/
---
spring:
profiles: 7902
server:
port: 7902
eureka:
instance:
hostname: eureka.server.two
client:
#\u8BBE\u7F6E\u670D\u52A1\u6CE8\u518C\u4E2D\u5FC3\u7684URL
service-url:
defaultZone: http://eureka.server.third:7903/eureka/,http://eureka.server.one:7901/eureka/,http://eureka.server.two:7902/eureka/
---
spring:
profiles: 7903
server:
port: 7903
eureka:
instance:
hostname: eureka.server.third
client:
#\u8BBE\u7F6E\u670D\u52A1\u6CE8\u518C\u4E2D\u5FC3\u7684URL
service-url:
defaultZone: http://eureka.server.one:7901/eureka/,http://eureka.server.two:7902/eureka/,http://eureka.server.third:7903/eureka/
idea启动配置: