1、构建步骤
1)eureka-server
(1)创建Meven工程
springcloud-eureka-7001
(2)导jar包
使用
spring-cloud-starter-netflix-eureka-server
<!-- spring-cloud-starter-eureka-server:已废弃 -->
<!-- spring-cloud-starter-netflix-eureka-server -->
<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>
</dependency>
(3)application.yml
server:
port: 7001
# Eureka配置
eureka:
instance:
# Eureka服务端的实例名字
hostname: localhost
client:
# 表示是否向 Eureka 注册中心注册自己 (这个模块本身是服务器,所以不需要)
register-with-eureka: false
# fetch-registry 是否拉取其他的服务;如果为 false,则表示自己为注册中心或服务提供者;服务消费者的话为 true
fetch-registry: false
# Eureka监控页面~
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
register-with-eureka
是否注册到eureka服务中;默认为true
fetch-registry
是否拉取其他的服务;默认为true
- 监控地址:
http://localhost:7001/
- 服务注册地址:
http://localhost:7001/eureka/
(4)主启动类
@EnableEurekaServer
开启 Eureka 服务端
@SpringBootApplication
@EnableEurekaServer
public class EurekaServer_7001 {
public static void main(String[] args) {
SpringApplication.run(EurekaServer_7001.class,args);
}
}
(5)测试
2)eureka-client
就是向 Eureka 中注册的一个个服务提供者
注册服务提供者
修改
springcloud-provider-dept-8001
(1)添加Eureka包
使用
spring-cloud-starter-netflix-eureka-client
<!-- spring-cloud-starter-netflix-eureka-client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
(2)配置 Eureka
- 在application.yml
# Eureka配置:配置服务注册中心地址
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka/
(3)主启动类
添加
@EnableEurekaClient
注解
@SpringBootApplication
@EnableEurekaClient
public class DepartmentProvider_8001 {
public static void main(String[] args) {
SpringApplication.run(DepartmentProvider_8001.class,args);
}
}
(4)测试
分别启动注册中心、服务提供者
如果此时停掉springcloud-provider-dept-8001 等30s后 监控会开启保护机制:
(5)修改默认描述信息
修改前
- 添加配置
# 配置 Eureka
eureka:
# ...
instance:
# 修改Eureka上的默认描述信息
instance-id: springcloud-provider-dept-8001
修改后
(6)配置服务加载的监控信息
1、在pom中导入依赖
spring-boot-starter-actuator
已在父工程的spring-boot-dependencies
中管理,可以省略版本号,直接导入
<!-- actuator完善监控信息 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2、在yml中添加
# 配置 Eureka
eureka:
# ...
instance:
# ...
# 以IP地址注册到服务中心
prefer-ip-address: true
# 监控端口配置
management:
endpoints:
web:
exposure:
# 开启 info,health;新版本中只默认开启了 health
include: info,health
3、配置info信息
有三种方式
-
方式一
在 yml 或 properties 中配置
未成功:读取不到
info:
project:
name: xxx
version: 1.0.0
-
方式二
使用Meven的打包插件,生成
build-info.properties
-
方式三
自定义
Myinfo.java
配置类,实现InfoContributor
接口加上
@Component
注解;更加灵活
package com.tuwer.springcloud.config;
import org.springframework.boot.actuate.info.Info;
import org.springframework.boot.actuate.info.InfoContributor;
import org.springframework.stereotype.Component;
import java.util.HashMap;
/**
* @author 土味儿
* Date 2022/2/11
* @version 1.0
*/
@Component
public class MyInfo implements InfoContributor {
@Override
public void contribute(Info.Builder builder) {
HashMap<String, Object> map = new HashMap<>();
// 可以从数据库获取信息
map.put("ServiceName","springcloud-provider-dept-8001");
map.put("version","1.0-SNAPSHOT");
map.put("author","tuwer");
builder.withDetails(map);
}
}
2、自我保护机制
好死不如赖活着
一句话总结就是:某时刻某一个微服务不可用,eureka 不会立即清理,依旧会对该微服务的信息进行保存!
- 默认情况下,当eureka server在一定时间内没有收到实例的心跳,便会把该实例从注册表中删除(默认是90秒),但是,如果短时间内丢失大量的实例心跳,便会触发eureka server的自我保护机制,比如在开发测试时,需要频繁地重启微服务实例,但是我们很少会把eureka server一起重启(因为在开发过程中不会修改eureka注册中心),当一分钟内收到的心跳数大量减少时,会触发该保护机制。可以在eureka管理界面看到Renews threshold和Renews(last min),当后者(最后一分钟收到的心跳数)小于前者(心跳阈值)的时候,触发保护机制,会出现红色的警告:
EMERGENCY!EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT.RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEGING EXPIRED JUST TO BE SAFE.
从警告中可以看到,eureka认为虽然收不到实例的心跳,但它认为实例还是健康的,eureka会保护这些实例,不会把它们从注册表中删掉。 - 该保护机制的目的是避免网络连接故障,在发生网络故障时,微服务和注册中心之间无法正常通信,但服务本身是健康的,不应该注销该服务,如果eureka因网络故障而把微服务误删了,那即使网络恢复了,该微服务也不会重新注册到eureka server了,因为只有在微服务启动的时候才会发起注册请求,后面只会发送心跳和服务列表请求,这样的话,该实例虽然是运行着,但永远不会被其它服务所感知。所以,eureka server在短时间内丢失过多的客户端心跳时,会进入自我保护模式,该模式下,eureka会保护注册表中的信息,不在注销任何微服务,当网络故障恢复后,eureka会自动退出保护模式。自我保护模式可以让集群更加健壮。
- 但是我们在开发测试阶段,需要频繁地重启发布,如果触发了保护机制,则旧的服务实例没有被删除,这时请求有可能跑到旧的实例中,而该实例已经关闭了,这就导致请求错误,影响开发测试。所以,在开发测试阶段,我们可以把自我保护模式关闭,只需在eureka server配置文件中加上如下配置即可:
eureka.server.enable-self-preservation=false
【不推荐关闭自我保护机制】
3、服务发现
获取注册中心中的微服务信息
1)Controller 中添加方法
package com.tuwer.springcloud.controller;
import com.tuwer.springcloud.pojo.Department;
import com.tuwer.springcloud.service.DepartmentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @author 土味儿
* Date 2022/2/9
* @version 1.0
*/
@RestController
public class DepartmentController {
// ...
@Autowired
private DiscoveryClient discoveryClient;
// ...
@GetMapping("/department/discovery")
public Object discovery(){
// 获取微服务列表的清单
List<String> services = discoveryClient.getServices();
System.out.println(services);
// 得到一个具体的微服务信息,通过微服务id,applicaioinName
List<ServiceInstance> instances = discoveryClient.getInstances("SPRINGCLOUD-PROVIDER-DEPT");
for (ServiceInstance instance : instances) {
System.out.println(
// 主机名称
instance.getHost() + "\t" +
// 端口号
instance.getPort() + "\t" +
// uri
instance.getUri() + "\t" +
// 服务id
instance.getServiceId()
);
}
return this.discoveryClient;
}
}
2)@EnableDiscoveryClient
在主启动类中加入 @EnableDiscoveryClient 注解;默认就是开启的,可以省略
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
public class DepartmentProvider_8001 {
public static void main(String[] args) {
SpringApplication.run(DepartmentProvider_8001.class,args);
}
}