Spring Cloud Eureka

eureka

服务注册与发现

Eureka 单节点搭建

pom.xml

1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

application.yml

1
2
3
4
5
6
7
8
9
eureka: 
client:
#是否将自己注册到Eureka Server,默认为true,由于当前就是server,故而设置成false,表明该服务不会向eureka注册自己的信息
register-with-eureka: false
#是否从eureka server获取注册信息,由于单节点,不需要同步其他节点数据,用false
fetch-registry: false
#设置服务注册中心的URL,用于client和server端交流
service-url:
defaultZone: http://localhost:7900/eureka/

application.properties

1
2
3
4
5
6
#是否将自己注册到Eureka Server,默认为true,由于当前就是server,故而设置成false,表明该服务不会向eureka注册自己的信息
eureka.client.register-with-eureka=false
#是否从eureka server获取注册信息,由于单节点,不需要同步其他节点数据,用false
eureka.client.fetch-registry=false
#设置服务注册中心的URL,用于client和server端交流
eureka.client.service-url.defaultZone=http://localhost:7900/eureka/
1
2
3
4
5
6
7
8
//启动类上添加此注解标识该服务为配置中心
@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}

Eureka高可用

高可用:可以通过运行多个Eureka server实例并相互注册的方式实现。Server节点之间会彼此增量地同步信息,从而确保节点中数据一致。

修改本机host文件,绑定一个主机名,单机部署时使用ip地址会有问题

节点 1:

1
2
3
4
5
6
7
8
9
10
11
12
#是否将自己注册到其他Eureka Server,默认为true 需要
eureka.client.register-with-eureka=true
#是否从eureka server获取注册信息, 需要
eureka.client.fetch-registry=true
#设置服务注册中心的URL,用于client和server端交流
#此节点应向其他节点发起请求
eureka.client.serviceUrl.defaultZone=http://ek2.com:7902/eureka/
#主机名,必填
eureka.instance.hostname=ek1.com
management.endpoint.shutdown.enabled=true
#web端口,服务是由这个端口处理rest请求的
server.port=7901

节点 2:

1
2
3
4
5
6
7
8
9
10
11
12
#是否将自己注册到其他Eureka Server,默认为true 需要
eureka.client.register-with-eureka=true
#是否从eureka server获取注册信息, 需要
eureka.client.fetch-registry=true
#设置服务注册中心的URL,用于client和server端交流
#此节点应向其他节点发起请求
eureka.client.serviceUrl.defaultZone=http://ek1.com:7902/eureka/
#主机名,必填
eureka.instance.hostname=ek2.com
management.endpoint.shutdown.enabled=true
#web端口,服务是由这个端口处理rest请求的
server.port=7902

两个节点的话,如下图内容 就算成功了

eureka

开启监控

Spring Boot 2.0 的Actuator只暴露了health和info端点,提供的监控信息无法满足我们的需求

在1.x中有n多可供我们监控的节点,官方的回答是为了安全….

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
1
2
3
#application.properties配置中
#开启所有端点
management.endpoints.web.exposure.include=*

服务注册

新建一个web项目,引入starterspring-cloud-starter-netflix-eureka-client

pom.xml

1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

application.yml

1
2
3
4
5
6
#注册中心
eureka:
client:
#设置服务注册中心的URL
service-url:
defaultZone: http://root:root@localhost:7900/eureka/

ps:不想注册,设置成false即可,实例演示结果:注册中心没有实例信息。找控制台204信息也没有找到。

1
2
3
4
5
spring: 
cloud:
service-registry:
auto-registration:
enabled: false

注册成功:

1
DiscoveryClient_API-LISTEN-ORDER/api-listen-order:30.136.133.9:port - registration status: 204

Eureka Server与Eureka Client之间的联系主要通过心跳的方式实现。心跳(Heartbeat)即Eureka Client定时向Eureka Server汇报本服务实例当前的状态,维护本服务实例在注册表中租约的有效性。

Eureka Client将定时从Eureka Server中拉取注册表中的信息,并将这些信息缓存到本地,用于服务发现。

Eureka原理

Register

服务注册:想要参与服务注册发现的实例首先需要向Eureka服务器注册信息,注册在第一次心跳发生时提交。


Renew

续租,心跳:Eureka客户需要每30秒发送一次心跳来续租

更新通知Eureka服务器实例仍然是活动的。如果服务器在90秒内没有看到更新,它将从其注册表中删除实例

如 [10:00 00] 第一次,[10:00 30]、[10:01 00]、[10:01:30] 最后一次,将剔除实例。


Fetch Registry

Eureka客户端从服务器获取注册表信息并将其缓存在本地。

之后,客户端使用这些信息来查找其他服务。

通过获取上一个获取周期和当前获取周期之间的增量更新,可以定期(每30秒)更新此信息。

节点信息在服务器中保存的时间更长(大约3分钟),因此获取节点信息时可能会再次返回相同的实例。Eureka客户端自动处理重复的信息。

在获得增量之后,Eureka客户机通过比较服务器返回的实例计数来与服务器协调信息,如果由于某种原因信息不匹配,则再次获取整个注册表信息。


Cancel

Eureka客户端在关闭时向Eureka服务器发送取消请求。这将从服务器的实例注册表中删除实例,从而有效地将实例从通信量中取出。


Time Lag

同步时间延迟

来自Eureka客户端的所有操作可能需要一段时间才能反映到Eureka服务器上,然后反映到其他Eureka客户端上。这是因为eureka服务器上的有效负载缓存,它会定期刷新以反映新信息。Eureka客户端还定期地获取增量。因此,更改传播到所有Eureka客户机可能需要2分钟。


Communication mechanism

通讯机制:Http协议下的Rest请求,默认情况下Eureka使用Jersey和Jackson以及JSON完成节点间的通讯


客户端配置选项

1
2
3
4
5
6
#续约发送间隔默认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

服务器端配置选项

1
2
3
4
#关闭自我保护模式
eureka.server.enable-self-preservation=false
#失效服务间隔
eureka.server.eviction-interval-timer-in-ms=3000

Eureka提供的API

元数据

Eureka的元数据有两种:标准元数据和自定义元数据。
标准元数据:主机名、IP地址、端口号、状态页和健康检查等信息,这些信息都会被发布在服务注册表中,用于服务之间的调用。
自定义元数据:可以使用eureka.instance.metadata-map配置,这些元数据可以在远程客户端中访问,但是一般不改变客户端行为,除非客户端知道该元数据的含义。

可以在配置文件中对当前服务设置自定义元数据,可后期用户个性化使用,元数据可以配置在eureka服务器和eureka的客户端上。

1
eureka.instance.metadata-map.dalao=kuro

自我保护机制

Eureka在CAP理论当中是属于AP , 也就说当产生网络分区时,Eureka保证系统的可用性,但不保证系统里面数据的一致性

默认开启,服务器端容错的一种方式,即短时间心跳不到达仍不剔除服务列表里的节点

1
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%时会触发保护机制

1
2
3
4
5
6
7
#服务端,关闭自我保护机制
eureka:
server:
#关闭自我保护
enable-self-preservation: false
#清理服务间隔时间,毫秒
eviction-interval-timer-in-ms: 5000

关闭后Eureka注册页面中会提示

eureka

多网卡选择

  1. ip注册
1
2
3
4
eureka:
instance:
prefer-ip-address: true
#表示将自己的ip注册到EurekaServer上。不配置或false,表示将操作系统的hostname注册到server
  1. 服务器有多个网卡,eh0,eh1,eh2,只有eh0可以让外部其他服务访问进来,而Eureka client将eh1和eh2注册到Eureka server上,这样其他服务就无法访问该微服务了。

  2. 指定Ip

    1
    2
    3
    4
    eureka:
    instance:
    prefer-ip-address: true
    ip-address: 实际能访问到的Ip

    如果设置了此时的ip-address,在元数据查看到就是此ip,其他服务也通过此ip来调用。或者使用spring.cloud.inetutils配置网卡选择

EurekaClient

EurekaClient 可以在客户端获取eureka服务器上的注册者信息

org.springframework.cloud.client.discovery与com.netflix.discovery.DiscoveryClient

1
2
3
4
5
6
7
@Autowired
DiscoveryClient discoveryClient;

//DiscoveryClient的API
String description();//获取实现类的描述。
List<String> getServices();//获取所有服务实例id。
List<ServiceInstance> getInstances(String serviceId);//通过服务id查询服务实例信息列表。

Eureka 健康检查

由于server和client通过心跳保持 服务状态,而只有状态为UP的服务才能被访问。看eureka界面中的status。

比如心跳一直正常,服务一直UP,但是此服务DB连不上了,无法正常提供服务。

此时,我们需要将 微服务的健康状态也同步到server。只需要启动eureka的健康检查就行。这样微服务就会将自己的健康状态同步到eureka。配置如下即可。

开启手动控制

在client端配置:将自己真正的健康状态传播到server。

1
2
3
4
5
6
7
8
9
10
eureka: 
client:
healthcheck:
#开启健康检查,需要引入actuator
enabled: true
instance:
#发送心跳给server的频率,每隔这个时间会主动心跳一次
lease-renewal-interval-in-seconds: 1
#Server从收到client后,下一次收到心跳的间隔时间。超过这个时间没有接收到心跳EurekaServer就会将这个实例剔除
lease-expiration-duration-in-seconds: 1

Client端配置Actuator

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

改变健康状态的Service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Service
public class HealthStatusService implements HealthIndicator{

private Boolean status = true;

public void setStatus(Boolean status) {
this.status = status;
}

@Override
public Health health() {
// TODO Auto-generated method stub
if(status)
return new Health.Builder().up().build();
return new Health.Builder().down().build();
}

public String getStatus() {
// TODO Auto-generated method stub
return this.status.toString();
}

测试用的Controller

1
2
3
4
5
6
@GetMapping("/health")
public String health(@RequestParam("status") Boolean status) {

healthStatusSrv.setStatus(status);
return healthStatusSrv.getStatus();
}

安全配置

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
1
2
spring.security.user.name=kuro
spring.security.user.password=123

eureka

如果服务注册报错以下错误,是默认开启了防止跨域攻击,在服务端增加配置类

1
Root name 'timestamp' does not match expected ('instance') for type [simple
1
2
3
4
5
6
7
8
9
10
11
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{

@Override
protected void configure(HttpSecurity http) throws Exception {
// TODO Auto-generated method stub
http.csrf().disable();
super.configure(http);
}
}

其他配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
"homePageUrl": "http://127.0.0.1:8084/",
"statusPageUrl": "http://127.0.0.1:8084/actuator/info",
"healthCheckUrl": "http://127.0.0.1:8084/actuator/health",

如果设置了

server:
servlet:
path: /path

需要:

eureka:
instance:
statusPageUrlPath: ${server.servlet.path}/actuator/info
healthCheckUrlPath: ${server.servlet.path}/actuator/health

最后更新: 2020年11月14日 10:08

原始链接: https://midkuro.gitee.io/2020/06/27/springcloud-eureka/

× 请我吃糖~
打赏二维码