Springboot版本为2.2.6.RELEASE,SpringCloud版本为Hoxton.SR3
一、Eureka原理
- 概述:Eureka来源于古希腊词汇,意为“发现了”;Eureka分为Server端和Client端
- 服务注册Register:所有的服务都需要要Eureka服务器注册信息;注册在第一次心跳发生时进行
- 心跳/续租Renew:Eureka客户端每隔30s需要向服务器发送一次心跳进行续租,如果Eureka服务端发现90s内某个客户端没有发送心跳,会将该客户端从注册表中剔除
- 拉取服务Fetch Register:Eureka客户端从Eureka服务端获取注册表信息并将其缓存在本地,Eureka客户端通过注册表信息来查找其他服务(增量更新)。
- 客户端关闭Cancel:Eureka客户端在关闭时向Eureka服务端发送取消请求,服务端将其从注册表中剔除。
- 同步时间延迟Time Lag:Eureka客户端的操作需要一定时间才能反映到Eureka服务器上,然后再反映到其他Eureka客户端上,这是因为eureka服务器上的有效负载缓存,它会定期刷新以反映新信息。Eureka客户端会定期地获取增量。信息更改同步到所有Eureka客户端可能需要2分钟。
- 通讯机制Communication mechanism:Http协议下的Rest请求,默认情况下Eureka使用Jersey和Jackson以及JSON完成节点间的通讯
- 自我保护机制:默认情况下,Eureka Server在一定时间内,没有接收到某个微服务心跳,会将该微服务注销(90S)。但是当网络故障时,微服务与Eureka Server之间无法正常通信,上述行为就非常危险,因为微服务正常,不应该注销。客户端每分钟续约数量小于客户端总数的85%时会触发保护机制。服务实例数:10个,期望每分钟续约数:10 * 2 = 20,期望阈值:20*0.85=17,自我保护少于17时 触发。
二、单节点Eureka的搭建
- 第一步:新建项目(模块),选择Spring Initlallzr
- 第二步:填写好项目(模块)的选项
- 第三步:选择依赖Eureka-server
- 第四步:在启动类上添加@EnableEurekaServer注解
package com.it00zyq.eureka_service;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
* EnableEurekaServer 开启Eureka服务
* @author it00zyq
*/
@EnableEurekaServer
@SpringBootApplication
public class EurekaServiceApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServiceApplication.class, args);
}
}
- 第五步:向application.yml中添加配置
eureka:
client:
# 是否从eureka server获取信息,单节点不需要同步,false
fetch-registry: false
# 是否将自己注册到eureka server,默认为true,自己就是server,不需要注册
register-with-eureka: false
# 设置服务注册中心的URL,同于client和server交流
service-url:
defaultZone: http://localhost:7900/eureka/
- 第六步:启动与访问
三、Eureka高可用集群
- 第一步:在一台机器上模拟集群,修改host文件域名解析,模拟多台机器
- 第二步:修改配置文件
公共配置文件
spring:
# 统一服务名称
application:
name: EurekaServer
# 根据配置文件启动不同的Eureka Server
profiles:
active: euk1
euk1配置文件
eureka:
client:
service-url:
# 向另一个Eureka Server节点注册自己
defaultZone: http://euk2.com:7002/eureka/
instance:
# 主机名称,必须唯一
hostname: euk1.com
server:
port: 7001
euk2配置文件
eureka:
client:
service-url:
# 向另一个Eureka Server节点注册自己
defaultZone: http://euk1.com:7001/eureka/
instance:
# 主机名称,必须唯一
hostname: euk2.com
server:
port: 7002
四、创建一个服务并注册到Eureka
-
第一步:创建项目(模块)
-
第二步:选择Maven依赖。web项目,引入依赖spring-cloud-starter-netflix-eureka-client
-
第三步:配置application.yml文件
eureka:
client:
service-url:
# 向一个Eureka Server节点进行服务注册
defaultZone: http://euk2.com:7002/eureka/
spring:
application:
name: code-service
server:
port: 8001
五、Eureka配置选项
# 客户端
#续约发送间隔默认30秒,心跳间隔
eureka.instance.lease-renewal-interval-in-seconds=5
#表示eureka client间隔多久去拉取服务注册信息,默认为30秒,对于api-gateway,如果要迅速获取服务注册状态,可以缩小该值,比如5秒
eureka.client.registry-fetch-interval-seconds=5
# 续约到期时间(默认90秒)
eureka.instance.lease-expiration-duration-in-seconds=60
# 服务端
#关闭自我保护模式
eureka.server.enable-self-preservation=false
#失效服务间隔
eureka.server.eviction-interval-timer-in-ms=3000
六、Eureka健康检查
Eureka Server已经内置了健康检查Actuator
- 客户端要添加健康检查只需以下依赖即可
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
- 配置健康检查开放的端点
# 健康检查配置
management:
endpoints:
web:
exposure:
# 开放所有端点
include: '*'
# 远程关闭服务的端口需要另外配置
# 配置可以远程关闭服务节点
endpoint:
shutdown:
enabled: true
- 访问主机+端口号+/actuator(http://localhost:8002/actuator)即可查看可访问信息端点
- 开启手动控制服务上下线的功能
# 默认开启的,可以不用配置
eureka:
client:
healthcheck:
# 开启远程控制服务的UP DOWN状态
enabled: true
- 添加控制服务上下限的服务层,需要实现HealthIndicator接口
package com.it00zyq.user_service.service;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Service;
/**
* 用于手动控制服务的上下线
* @author it00zyq
*/
@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();
}
}
- 添加Controller,实现远程控制
@Autowired
private HealthStatusService healthStatusService;
@PostMapping("test/health/{status}")
public void test5(@PathVariable(name = "status") Boolean status) {
healthStatusService.setStatus(status);
}
- 效果