1、Eureka 介绍与原理
理解:Eureka就像一个物业管理公司,其他微服务就像小区的住户,每个住户入住时都要向物业管理公司注册,并定时向物业公司交管理费
介绍:
- Eureka是一个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移。
- Eureka主管服务注册与发现,在微服务中,以后了这两者,只需要使用服务的标识符(就是那个在每个服务的yml文件中取得服务名称),就可以访问到服务,不需要修改服务调用的配置文件。
- Eureka遵循AP原则(高可用,分区容错性),因为使用了自我保护机制所以保证了高可用。
原理:
- Eureka使用的是C-S结构(客户端-服务端)
- 两大组件:Eureka Server(提供注册服务)、 Eureka Client(JAVA客户端,负责发送心跳)
- 系统中的其他微服务使用 Eureka Client 连接到 Eureka Server 维持心跳连接(即注册)。SpringCloud 的其他模块(比如Zuul)可以通过 Eureka Server 来发现系统中的微服务并加以调用。
Eureka 两大组件:
- Eureka Server 提供服务注册服务。各个节点启动后,会在 EurekaServer 中进行注册,这样 EurekaServer 中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。
- Eureka Client 是一个 Java 客户端,用于简化 Eureka Server 的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向 Eureka Server 发送心跳(默认周期为30秒)。如果 Eureka Server 在多个心跳周期内没有接收到某个节点的心跳,Eureka Server 将会从服务注册表中把这个服务节点移除(默认90秒)。
微服务的三大角色:
- Eureka Server 提供服务注册和发现
- Service Provider 服务提供方将自身服务注册到 Eureka,从而使服务消费方能够找到
- Service Consumer 服务消费方从 Eureka 获取注册服务列表,从而能够消费服务
2、构建 Eureka Server
新建 cloud-eureka-server7001 子模块.
在 Spring Cloud 中添加新组件的常规两个步骤:
- 新增组件的 Maven 坐标
- 在主启动类上面,标注启动该组件技术的相关注解标签 @EnableXxx
2.1、在新建子模块的 pom 文件中导入依赖:
<!-- Eureka-server 端组件 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!-- 引入自己定义的 api 通用包,可以使用 Payment 支付 Entity -->
<dependency>
<groupId>per.cjh.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- boot web actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 一般通用配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
2.2、配置 yml
server:
port: 7001
eureka:
instance:
hostname: localhost # eureka 服务端的实例名称
client:
register-with-eureka: false # 向 eureka 注册自己。false 表示不向注册中心注册自己
fetch-registry: false # 提取注册表。false 表示自己就是注册中心,我的职责是就是维护服务实例,并不需要去检索服务
service-url:
# 设置与 Eureka Server 交互的地址查询服务和注册服务都需要依赖这个地址,这是本注册中心对外暴露的地址
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
2.3、在主启动类中启动服务组件
因为 Eureka 有两个组件,所以我们必须在主启动类上声明该服务是服务端组件还是客户端组件。
@SpringBootApplication
@EnableEurekaServer // 服务器端启动类,接受其他微服务注册进来
public class EurekaServer {
public static void main(String[] args) {
SpringApplication.run(EurekaServer.class, args);
}
}
启动 7001 服务,测试访问 localhost:7001/ 会出现 Eureka 界面,界面中提示还没有注册服务。
3、将已有的部门微服务注册进 Eureka 服务中心
1. 增加依赖:
<!-- 引入 Eureka-client 端组件,将该服务注册进注册中心 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2. 修改 yml:
在 yml 文件中增加下面这条配置信息。该配置是为了让当前模块作为客户端,并获知 Eureka 服务端的位置,让当前客户端可以去注册自己的信息。
eureka:
client:
# 表示是否将自己注册进 EurekaServer,默认为 true。
register-with-eureka: true
# 是否从 EurekaServer 抓取已有的可用的注册信息,默认为 true,单节点无所谓,集群必须设置为 true 才能配合 ribbon 使用负载均衡
fetch-registry: true
service-url:
defaultZone: http://localhost:7001/eureka
3. 修改 Eureka 客户端模块的主启动类:
增加@EnableEurekaClient注解
@SpringBootApplication
@EnableEurekaClient
public class Provider8001_APP {
public static void main(String[] args) {
SpringApplication.run(Provider8001_APP.class,args);
}
}
4、测试访问 Eureka 服务端,服务端调用 Eureka 客户端
启动 7001 服务端,再启动 8001 客户端。访问服务器端地址 http://localhost:7001 ,显示 Eureka 主页。
没有将 8001 配置成 Eureka 客户端之前:
将 8001 配置成 Eureka 客户端之后:
8001 这个客户端的名字,是在其 yml 文件中配置的,在前文案例(二)中有在 8001 微服务模块配置如下信息:
上面配置的这个名字将作为该模块的名称。
5、actuator与注册微服务信息完善
要完善的三个内容
- 主机名称:服务名称修改(人性化)
- 访问信息有IP信息提示(方便定位)
- 微服务 info 内容详细信息(方便维护)
5.1、主机名称:服务名称修改(人性化)
主机名称未修改之前:
修改 microservicecloud-provider-dept-8001 客户端 YML 配置文件,添加如下配置:
instance:
instance-id: microservicecloud-dept8001
如下图:
主机名称修改之后:
5.2、访问信息有 IP 信息提示(方便定位)
访问信息未修改之前:
光标放到微服务链接之上,在页面左下角提示如下访问信息,信息不够准确,没有 IP 的提示
修改 microservicecloud-provider-dept-8001 的 YML 配置文件,添加如下配置:
prefer-ip-address: true # 访问路径可以显示 IP 地址(开启 ip 前缀显示)
如下图:
IP 前缀提示修改之后:
5.3、微服务 info 网页内容显示详细信息(方便维护)
点击 Eureka 页面的 Status 链接,进入 info 页面。info 页面未修改之前:网页404
修改 microservicecloud-provider-dept-8001 微服务,在 pom 文件中引入 actuator 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
总的父工程 microservicecloud 修改 pom.xml 添加构建 build 信息
<build>
<finalName>microservicecloud</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<delimiters>
<delimit>$</delimit>
</delimiters>
</configuration>
</plugin>
</plugins>
</build>
修改 microservicecloud-provider-dept-8001 模块的 YML 文件,添加如下配置:
info:
app.name: per.cjh-microservicecloud
company.name: per.jch
build.artifactId: $project.artifactId$
build.version: $project.version$
如下图:
修改之后的 info 网页:
6、Eureka 的自我保护机制
1. 介绍:
Eureka 的自我保护机制主要是为了网络异常时保持高可用设计的,当在 Eureka 中注册的微服务超过设定是时间内(默认90秒)没有向 Eureka 服务端发送心跳,该微服务会进入自我保护模式。某时刻某一个微服务不可用了,eureka不会立刻清理,依旧会对该微服务的信息进行保存在自我保护模式中,Eureka 会保护服务注册表中的信息,不会注销任何服务实例,直至收到的心跳数恢复至阈值以上,该微服务退出自我保护模式。
2. 理解:
Eureka 的设计哲学是宁可保留错误的服务信息,也不盲目注销可能健康的服务。所以异常的服务不会被注销,而是进入了自我保护模式。
3. 自我保护模式的开关:
在 Eureka Server 模块下的 yml 文件中添加配置信息即可,true 表示打开自我保护模式;false 表示关闭自我保护模式(不推荐)
server:
enable-self-preservation: false
7、集群配置
- 新建microservicecloud-eureka-7002 和 microservicecloud-eureka-7003
- 以 7001 的 pom 文件为模板粘贴到 7002 和 7003模块中
- 拷贝 7001 的主启动类,并修改至使其契合于 7002和7003 模块
- 修改映射配置文件
- 找到 C:\Windows\System32\drivers\etc 路径下的 hosts 文件
- 修改映射配置添加进 hosts 文件
- 完成3台 Eureka 服务器端的 yml 配置
目的:在7001 上写入 7002/7003,在7002上写入 7001/7003,即分别写入对方的位置,实现集群
7001 的 yml 文件如下:
server:
port: 7001
eureka:
instance:
hostname: eureka7001.com # Eureka 服务端的实例名称
client:
register-with-eureka: false #false 表示不向注册中心注册自己
fetch-registry: false #false 表示自己就是注册中心,职责是维护实例,不参加检索
service-url:
# 单机版 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #设置 eureka server 的交互地址,即对外暴露的地址
defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
7002 的 yml 文件如下:
server:
port: 7002
eureka:
instance:
hostname: eureka7002.com # Eureka 服务端的实例名称
client:
register-with-eureka: false #false 表示不向注册中心注册自己
fetch-registry: false #false 表示自己就是注册中心,职责是维护实例,不参加检索
service-url:
# 单机版 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #设置 eureka server 的交互地址,即对外暴露的地址
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7003.com:7003/eureka/
7003 的 yml 文件如下:
server:
port: 7003
eureka:
instance:
hostname: eureka7003.com # Eureka 服务端的实例名称
client:
register-with-eureka: false #false 表示不向注册中心注册自己
fetch-registry: false #false 表示自己就是注册中心,职责是维护实例,不参加检索
service-url:
# 单机版 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #设置 eureka server 的交互地址,即对外暴露的地址
defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7001.com:7001/eureka/
- 将 8001 微服务发布到上面3台 eureka 集群配置中
8001 yml 配置文件的原 defaultZone 属性如下:
defaultZone: http://eureka7001.com:7001/eureka/
修改8001 yml 配置文件的 defaultZone 属性如下:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
- 测试 eureka 集群,运行 7001 - 7003,然后运行8001客户端,访问其中某一台 Eureka 服务器,如: http://eureka7002.com:7002/
页面效果,可以看到另外两台 eureka 服务器,和 8001 这台客户端:
8、两个注册中心的比较:Eureka 和 Zookeeper
CAP设计原则不同:
Eureka遵守AP,Zookeeper遵守CP(C:强一致性,A:高可用,P:分区容错性,三者只能选其二,在分布式架构下P必选)
Eureka可以较好的应对网络故障导致部分节点失去连接的情况,不会导致整个注册服务系统的瘫痪。