Spring Cloud Eureka
一、Eureka简介
1、背景
传统应用中,组件之间的调用,通过有规范的约束的接口来实现,从而实现不同模块间良好的协作。但是被拆分成微服务后,每个微服务实例的网络地址都可能动态变化,数量也会变化,使得原来硬编码的地址失去了作用。需要一个中心化的组件来进行服务的登记和管理。
2、介绍
Eureka来源于古希腊词汇,意为“发现了”,是一个RESTful风格的服务,是一个用于服务发现和注册的基础组件,是搭建Spring Cloud微服务的前提之一,它屏蔽了Server和client的交互细节,使得开发者将精力放到业务上。
3、注册中心的好处
不用关心有多少提供方。
4、注册中心有哪些
- Eureka
- Nacos
- Consul
- Zookeeper
二、服务注册与发现
服务注册与发现包括两部分,一个是服务器端,另一个是客户端。
1、服务器端
Server是一个公共服务,为Client提供服务注册和发现的功能,维护注册到自身的Client的相关信息,同时提供接口给Client获取注册表中其他服务的信息,使得动态变化的Client能够进行服务间的相互调用。
功能
- 服务注册表。记录每个注册上来微服务信息,比如服务名称、IP、端口等。注册表提供 查询API(查询可用的微服务实例)和管理API(用于服务的注册和注销)。
- 服务注册。将微服务信息注册到注册中心。
- 服务发现。查询可用微服务列表及其网络地址。
- 服务检查。定时检查已注册的服务。发现某服务长时间未提供心跳包,就从注册表中移除。
自我保护机制
机制
Eureka在CAP理论当中是属于AP,也就说当产生网络分区时,Eureka保证系统的可用性,但不保证系统里面数据的一致性。
默认开启,服务器端容错的一种方式,即短时间心跳不到达仍不剔除服务列表里的节点。
EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.
默认情况下,Eureka Server在一定时间内,没有接收到某个微服务心跳,会将某个微服务注销(90S)。但是当网络故障时,微服务与Server之间无法正常通信,上述行为就非常危险,因为微服务正常,不应该注销。
Eureka Server通过自我保护模式来解决整个问题,当Server在短时间内丢失过多客户端时,那么Server会进入自我保护模式,会保护注册表中的微服务不被注销掉。当网络故障恢复后,退出自我保护模式。
思想
宁可保留有不健康的,也不盲目注销任何健康的服务。
机制触发条件
客户端每分钟续约数量小于客户端总数的85%时会触发保护机制
(当每分钟心跳次数( renewsLastMin ) 小于 numberOfRenewsPerMinThreshold 时,并且开启自动保护模式开关( eureka.server.enable-self-preservation = true ) 时,触发自我保护机制,不再自动过期租约。)
numberOfRenewsPerMinThreshold = expectedNumberOfRenewsPerMin * 续租百分比( eureka.server.renewalPercentThreshold, 默认0.85 )
expectedNumberOfRenewsPerMin = 当前注册的应用实例数 x 2
默认情况下,注册的应用实例每半分钟续租一次,那么一分钟心跳两次,因此 x 2 。
服务实例数:10个,期望每分钟续约数:10 * 2=20,期望阈值:20*0.85=17,自我保护少于17时 触发。
关闭自我保护机制
eureka:
server:
enable-self-preservation: false
清理时间
eureka:
server:
eviction-interval-timer-in-ms: 3000
2、客户端
Client将自己的服务信息通过一定的方式登记到Server上,并在正常范围内维护自己信息一致性,方便其他服务发现自己,同时可以通过Server获取到自己依赖的其他服务信息,完成服务调用,还内置了负载均衡器,用来进行基本的负载均衡。
- Register注册。微服务启动时,将自己信息注册到注册中心,注册中心存储这些信息(内存中)。服务启动后第一次心跳提交注册。
- FetchRegistry拉取注册中心列表。定时去注册中心拉取注册表信息,缓存到client本地。避免每次请求都去注册中心查找。通过获取上一个获取周期和当前获取周期之间的增量更新,可以定期(每30秒)更新此信息。节点信息在服务器中保存的时间更长(大约3分钟),因此获取节点信息时可能会再次返回相同的实例。Eureka客户端自动处理重复的信息。在获得增量之后,Eureka客户机通过比较服务器返回的实例计数来与服务器协调信息,如果由于某种原因信息不匹配,则再次获取整个注册表信息。
- Renew续约、心跳。微服务与注册中心通过某种机制(心跳)通讯。如果服务器在90秒内(可配置)没有看到更新,它将从其注册表中删除实例。
- Cancel注销。Eureka客户端在关闭时向Eureka服务器发送取消请求。这将从服务器的实例注册表中删除实例,从而有效地将实例从通信量中取出。
- TimeLag同步时间延迟。来自Eureka客户端的所有操作可能需要一段时间才能反映到Eureka服务器上,然后反映到其他Eureka客户端上。这是因为eureka服务器上的有效负载缓存,它会定期刷新以反映新信息。Eureka客户端还定期地获取增量。因此,更改传播到所有Eureka客户机可能需要2分钟。
- Communication Mechanism通讯机制。Http协议下的Rest请求,默认情况下Eureka使用Jersey和Jackson以及JSON完成节点间的通讯
- 调用服务。解析服务名和具体地址对应关系,找到具体地址发起请求。
三、配置
1、注册中心配置
(1)依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
(2)配置文件
server:
port: 7901
eureka:
client:
# 是否将自己注册到Eureka Server,默认是true,由于当前就是server,所以设置false,表明改服务不会注册到Eureka Server
register-with-eureka: true
# 是否从Eureka Server获取注册信息,由于当前是单节点,不需要同步其他节点数据,用false
fetch-registry: true
# 是否过滤掉非Up的实例
# filter-only-up-instances: true
# 设置服务注册中心的url 用于client和server交流
service-url:
defaultZone: http://root:123456@euk2.com:7902/eureka/
# 客户端拉取服务端注册列表信息间隔 默认30s 对于网关如果需要迅速获取服务注册状态 可以调下 比如5s
registry-fetch-interval-seconds: 30
instance:
hostname: euk1.com
# 续约 心跳间隔 默认30s
lease-renewal-interval-in-seconds: 30
# 续约到期时间 默认90s
lease-expiration-duration-in-seconds: 90
# 关闭自我保护机制
server:
enable-self-preservation: false
3、注册成功
DiscoveryClient_EUREKASERVER/localhost:EurekaServer:7901 - registration status: 204
4、高可用
多个server之间互相注册
server:
port: 7902
eureka:
client:
# 是否将自己注册到Eureka Server,默认是true,由于当前就是server,所以设置false,表明改服务不会注册到Eureka Server
register-with-eureka: true
# 是否从Eureka Server获取注册信息,由于当前是单节点,不需要同步其他节点数据,用false
fetch-registry: true
# 是否过滤掉非Up的实例
# filter-only-up-instances: true
# 设置服务注册中心的url 用于client和server交流
service-url:
defaultZone: http://root:123456@euk1.com:7901/eureka/
# 客户端拉取服务端注册列表信息间隔 默认30s 对于网关如果需要迅速获取服务注册状态 可以调下 比如5s
registry-fetch-interval-seconds: 30
instance:
hostname: euk2.com
# 续约 心跳间隔 默认30s
lease-renewal-interval-in-seconds: 30
# 续约到期时间 默认90s
lease-expiration-duration-in-seconds: 90
5、DiscoveryClient
org.springframework.cloud.client.discovery.DiscoveryClient
SpringCloud对注册中心client的抽象封装,提供公用功能。是客户端进行服务发现的核心接口,是spring cloud用来进行服务发现的顶级接口,在common中可以看到其地位。在Netflix Eureka和Consul中都有具体的实现类。
com.netflix.discovery.DiscoveryClient
Eureka注册中心客户端的接口,功能更丰富。
6、多网卡选择
IP注册
# 表示将自己的ip注册到EurekaServer上。不配置或false,表示将操作系统的hostname注册到server
eureka:
instance:
prefer-ip-address: true
# 指定IP
ip-address: 实际能访问到的Ip
排除其他网卡
spring:
cloud:
inetutils:
ignored-interfaces: "VMware Virtual Ethernet Adapter for VMnet1,Microsoft Wi-Fi Direct Virtual Adapter #2,VMware Virtual Ethernet Adapter for VMnet8"
7、健康检查
由于server和client通过心跳保持 服务状态,而只有状态为UP的服务才能被访问。看eureka界面中的status。
比如心跳一直正常,服务一直UP,但是此服务DB连不上了,无法正常提供服务。
此时,我们需要将微服务的健康状态也同步到server。只需要启动eureka的健康检查就行。这样微服务就会将自己的健康状态同步到eureka。配置如下即可。
手动开启
在client端配置:将自己真正的健康状态传播到server。
eureka:
client:
healthcheck:
enabled: true
client端需要开启Actuator
改变健康状态的Service
/**
* 自定义修改服务状态
* actuator上报时会上报修改后的状态
* 优点:人工控制服务是否可用 应对服务可用 业务不可用的情况 比如短信平台短信数量到达上限
*/
@Service
public class HealthStatusService implements HealthIndicator {
private Boolean status = true;
public void setStatus(Boolean status) {
this.status = status;
}
@Override
public Health health() {
if (status)
return new Health.Builder().up().build();
return new Health.Builder().down().build();
}
public String getStatus() {
return this.status.toString();
}
}
入口
@GetMapping("/statusChange")
public String statusChange(@RequestParam("status") Boolean status) {
healthStatusService.setStatus(status);
return healthStatusService.health().getStatus().getCode();
}
8、安全配置
开启安全验证
spring:
# 开启安全认证 登录
security:
user:
name: root
password: 123456
如果服务启动报错
Root name 'timestamp' does not match expected ('instance') for type [simple
是默认开启了防止跨域攻击
手动关闭防止跨域攻击
/**
* csrf配置类
* Root name 'timestamp' does not match expected ('instance') for type [simple type, class com.netflix.appinfo.InstanceInfo
* 关闭防止跨域攻击
*/
@EnableWebSecurity
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.csrf().disable();//关闭csrf认证,否则会报错Root name 'timestamp' does not match expected ('instance')
super.configure(http);
}
}
四、Rest服务调用Eureka
1、官方文档 https://github.com/Netflix/eureka/wiki/Eureka-REST-operations
Operation | HTTP action | Description |
---|---|---|
Register new application instance | POST /eureka/v2/apps/appID | Input: JSON/XMLpayload HTTPCode: 204 on success |
De-register application instance | DELETE /eureka/v2/apps/appID/instanceID | HTTP Code: 200 on success |
Send application instance heartbeat | PUT /eureka/v2/apps/appID/instanceID | HTTP Code: * 200 on success * 404 if instanceIDdoesn’t exist |
Query for all instances | GET /eureka/v2/apps | HTTP Code: 200 on success Output: JSON/XML |
Query for all appID instances | GET /eureka/v2/apps/appID | HTTP Code: 200 on success Output: JSON/XML |
Query for a specific appID/instanceID | GET /eureka/v2/apps/appID/instanceID | HTTP Code: 200 on success Output: JSON/XML |
Query for a specific instanceID | GET /eureka/v2/instances/instanceID | HTTP Code: 200 on success Output: JSON/XML |
Take instance out of service | PUT /eureka/v2/apps/appID/instanceID/status?value=OUT_OF_SERVICE | HTTP Code: * 200 on success * 500 on failure |
Move instance back into service (remove override) | DELETE /eureka/v2/apps/appID/instanceID/status?value=UP (The value=UP is optional, it is used as a suggestion for the fallback status due to removal of the override) | HTTP Code: * 200 on success * 500 on failure |
Update metadata | PUT /eureka/v2/apps/appID/instanceID/metadata?key=value | HTTP Code: * 200 on success * 500 on failure |
Query for all instances under a particular vip address | GET /eureka/v2/vips/vipAddress | * HTTP Code: 200 on success Output: JSON/XML * 404 if the vipAddressdoes not exist. |
Query for all instances under a particular secure vip address | GET /eureka/v2/svips/svipAddress | * HTTP Code: 200 on success Output: JSON/XML * 404 if the svipAddressdoes not exist. |
2、服务状态
get方式请求
/eureka/status
使用浏览器请求url会返回服务器状态信息
3、注册服务列表信息查看
get方式请求
/eureka/apps
4、服务具体信息查看
get方式请求
/eureka/apps/{appname}/{id}
5、服务续约
put方式请求
/eureka/apps/{appname}/{id}?lastDirtyTimestamp={}&status=up
6、更改服务状态
put方式请求
/eureka/apps/{appname}/{id}/status?lastDirtyTimestamp={}&value={UP/DOWN}
7、删除更新状态
delete方式请求
/eureka/apps/{appname}/{id}/status?lastDirtyTimestamp={}&value={UP/DOWN}
8、元数据
标准元数据
主机名、IP地址、端口号、状态页和健康检查等信息,这些信息都会被发布在服务注册表中,用于服务之间的调用。
自定义元数据
可以使用eureka.instance.metadata-map配置,这些元数据可以在远程客户端中访问,但是一般不改变客户端行为,除非客户端知道该元数据的含义。
可以配置在eureka服务器和eureka的客户端上
# 自定义权重
eureka:
instance:
metadata-map:
weight: 6
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本