一、简介
Eureka 是 Netflix 开发的服务发现框架,本身是一个基于 REST 的服务,主要用于定位运行在 AWS 域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的。SpringCloud 将它集成在其子项目 spring-cloud-netflix 中,以实现 SpringCloud 的服务发现功能。
Eureka包含两个组件:
- Eureka Server
- Eureka Client
Eureka Server
Eureka Server 提供服务注册服务,各个节点启动后,会在 Eureka Server 中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。
Eureka Client
Eureka Client 是一个 java 客户端,用于简化与 Eureka Server 的交互,客户端同时也就是一个内置的、使用轮询 (round-robin) 负载算法的负载均衡器。
安全机制
在应用启动后,将会向 Eureka Server 发送心跳,默认周期为30秒,如果 Eureka Server 在多个心跳周期内没有接收到某个节点的心跳,Eureka Server 将会从服务注册表中把这个服务节点移除(默认90秒)。
Eureka Server 之间通过复制的方式完成数据的同步,Eureka 还提供了客户端缓存机制,即使所有的 Eureka Server 都挂掉,客户端依然可以利用缓存中的信息消费其他服务的 API 。
综上,Eureka 通过心跳检查、客户端缓存等机制,确保了系统的高可用性、灵活性和可伸缩性。
二、构建服务注册中心 Eureka(单机)
项目一般分为下面几个步骤: 1、创建模块 2、导入依赖 3、配置文件 4、启动类启动配置
2.1 创建父 maven 工程【springcloud】
- 新建的父工程 pom文件中 packaging 是 pom 模式。
- 主要是定义 pom 文件,将后续各个子模块公用的 jar 包等统一提取出来,类似一个抽象父类。
导入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>con.cyo</groupId>
<artifactId>springcloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>springcloud-eureka-7001</module>
<module>springcloud-provider-8001</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring-cloud.version>Hoxton.SR12</spring-cloud.version>
<springboot.version>2.3.12.RELEASE</springboot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${springboot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
2.2 创建子 module 【springcloud-eureka-7001】
创建 Spring Initializr 项目,以后的子模块都以这样的方式创建。
导入依赖 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>con.cyo</groupId>
<artifactId>springcloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.cyo</groupId>
<artifactId>springcloud-eureka-7001</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springcloud-eureka-7001</name>
<description>Demo project for Spring Boot</description>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
</project>
编写配置类 application.yml
server:
port: 7001
eureka:
instance:
hostname: localhost
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
spring:
application:
name: springcloud-eureka-7001
启动类启动配置
@SpringBootApplication
@EnableEurekaServer
public class SpringcloudEureka7001Application {
public static void main(String[] args) {
SpringApplication.run(SpringcloudEureka7001Application.class, args);
}
}
2.3 访问 eureka 的监控页面
浏览器访问 http://localhost:7001,界面如下图
三、创建一个服务提供者【springcloud-provider-8001】
导入依赖 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>con.cyo</groupId>
<artifactId>springcloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.cyo</groupId>
<artifactId>springcloud-provider-8001</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springcloud-provider-8001</name>
<description>Demo project for Spring Boot</description>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
编写配置类 application.yml
server:
port: 8001
spring:
application:
name: springcloud-provider
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka/
instance:
instance-id: springcloud-provider-8001
启动类启动配置
@SpringBootApplication
@EnableEurekaClient
@RestController
public class SpringcloudProvider8001Application {
public static void main(String[] args) {
SpringApplication.run(SpringcloudProvider8001Application.class, args);
}
@Value("${server.port}")
String port;
@RequestMapping("/hi")
public String home(@RequestParam(value = "name", defaultValue = "cyo") String name) {
return "hi " + name + " ,i am from port:" + port;
}
}
需要指明 spring.application.name,这个很重要,这在以后的服务与服务之间相互调用一般都是根据这个name。
启动工程,打开http://localhost:7001 此时,有一个服务已经注册进来,服务名就是 spring.application.name 中设置的名字,代表一个服务。 这时候浏览器打开: http://localhost:8001/hi?name=aa,在浏览器会看到
hi aa ,i am from port:8001
四、Eureka 自我保护机制
当停掉【springcloud-provider-8001】后,Eureka 会启动自我保护机制。 这时候浏览器打开 Eureka 监控页面: http://localhost:7001/ 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 可能存在维护了错误的实例列表(当它们没有启动的时候,Eureka却把它当成启动的了);Renews 值小于 Threshold 值,因此剩下未过期的都是安全的。
原因分析
Eureka Server 在运行期间会去统计心跳失败比例在 15 分钟之内是否低于 85%,如果低于 85%,Eureka Server 会将这些实例保护起来,让这些实例不会过期,但是在保护期内如果服务刚好这个服务提供者非正常下线了,此时服务消费者就会拿到一个无效的服务实例,此时会调用失败,对于这个问题需要服务消费者端要有一些容错机制,如重试,断路器等。
我们在单机测试的时候很容易满足心跳失败比例在 15 分钟之内低于 85%,这个时候就会触发 Eureka 的保护机制,一旦开启了保护机制,则服务注册中心维护的服务实例就不是那么准确了,此时我们可以使用 eureka.server.enable-self-preservation=false 来关闭保护机制,这样可以确保注册中心中不可用的实例被及时的剔除(不推荐)。
自我保护模式被激活的条件是:在 1 分钟后,Renews (last min) < Renews threshold 。
这两个参数的意思:
Renews threshold:Eureka Server 期望每分钟收到客户端实例续约的总数。 Renews (last min):Eureka Server 最后 1 分钟收到客户端实例续约的总数。
进一步的详细内容:https://www.cnblogs.com/xishuai/p/spring-cloud-eureka-safe.html
参考资料
https://blog.csdn.net/forezp/article/details/81040925 https://www.cnblogs.com/xishuai/p/spring-cloud-eureka-safe.html
|