前言
本篇主要内容为 Eureka 简要设置、discovery 服务发现、Eureka Server 自我保护机制
一、actuator 微服务信息完善
在生产环境中,我们会将微服务部署在不同的服务器上,为了方便查看、管理和定位等,我们需要将微服务的ip暴露出来,这样后续有需要时,就能很容易的知道微服务是部署在哪一台服务器上。
1.1 主机名称:服务名称修改
1.1 打开需要修改的子模块的 application.yml 配置文件,例如 cloud-provider-payment8001 模块
1.2 增加 instance:instance-id: 自定义的主机名称:服务名称
server:
port: 8001
spring:
application:
name: cloud-payment-service
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.126.100:3306/db2019?useUnicode=true&characterEncoding=utf-8 #mysql地址 根据实际情况修改
username: root #mysql登录账号,根据实际情况修改
password: abc123 #mysql登录密码,根据实际情况修改
eureka:
client:
register-with-eureka: true #表示将自己注册进 EurekaServer 中,默认为 true
fetch-registry: true #是否从 EurekaServer 中抓取已有的注册信息,默认为 true。单节点无所谓,集群必须设置为true才能配合 ribbon 使用负载均衡
service-url:
#defaultZone: http://localhost:7001/eureka #单机版
defaultZone: http://eureka7001.com:7001/eureka,http//eureka7002.com:7002/eureka #集群版
instance:
instance-id: payment8001 #自定义显示主机名称
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.atguigu.springcloud.bean
1.3 重启当前子模块,然后刷新 eureka 可视化页面
1.2、设置显示子模块服务ip和端口信息
鼠标悬浮主机名称,页面右下角显示当前子模块服务运行的ip和端口
这个我本地没有设置也能正常显示,不知道是不是因为版本问题,而且设置成false,也关不掉。设置方法也蛮记录下,以备不时之需。
2.1 打开要设置的子模块中的 application.yml 文本
这边还是以 cloud-provider-payment8001 为例
2.2 增加 instance:prefer-ip-address:false 设置
server:
port: 8001
spring:
application:
name: cloud-payment-service
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.126.100:3306/db2019?useUnicode=true&characterEncoding=utf-8 #mysql地址 根据实际情况修改
username: root #mysql登录账号,根据实际情况修改
password: abc123 #mysql登录密码,根据实际情况修改
eureka:
client:
register-with-eureka: true #表示将自己注册进 EurekaServer 中,默认为 true
fetch-registry: true #是否从 EurekaServer 中抓取已有的注册信息,默认为 true。单节点无所谓,集群必须设置为true才能配合 ribbon 使用负载均衡
service-url:
#defaultZone: http://localhost:7001/eureka #单机版
defaultZone: http://eureka7001.com:7001/eureka,http//eureka7002.com:7002/eureka #集群版
instance:
instance-id: payment8001 #自定义显示主机名称
prefer-ip-address: false #访问路径显示ip地址
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.atguigu.springcloud.bean
2.3 重启子模块后,刷新eureka 可视化页面
二、开启服务发现 Discovery
对于Eureka 中注册的微服务,可以通过服务发现来获取该服务的信息。下面以支付模块8001(cloud-privoder-payment8001)为例,记录如何开启服务发现。
2.1 修改 PaymentController.Java,增加获取服务发现相关访问接口
在 PaymentController.java 中增加导入 DiscoveryClient
@Resource
private DiscoveryClient discoveryClient;
PS: 此处的导入的应为:org.springframework.cloud.client.discovery.DiscoveryClient
然后增加获取微服务信息的访问接口
/**
* 获取 Eureka 中注册的微服务信息
* @return
*/
@GetMapping(value = "/payment/discovery")
private CommonResult discovery() {
//获取服务列表
List<String> serviceList = discoveryClient.getServices();
for (String serviceStr: serviceList) {
log.info(">>> 服务对象 {}", serviceStr);
}
//获取指定微服务信息
List<ServiceInstance> serviceInstanceList = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
for (ServiceInstance instance: serviceInstanceList) {
log.info(">>> 获取指定微服务 {} 信息, 主机名称: {} , 端口: {}, 服务访问路径: {}", instance.getServiceId(), instance.getHost(), instance.getPort(), instance.getUri());
}
return new CommonResult(200, "操作成功", this.discoveryClient);
}
2.2 在支付8001子模块主启动类中增加 @EnableDiscoveryClient 注解
在新版本中,即使不增加 @EnableDiscoveryClient 注解,也能正常获得微服务相关信息。
package com.atguigu.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
/**
* @auther He
* @date 2022-04-25 21:13
*/
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
public class PaymentMain8001 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain8001.class, args);
}
}
2.3 启动、测试
先启动 Eureka 相关的服务,再启动 支付8001 子模块。
启动成功后,在Eureka Server 可视化页面中可以看到 支付8001 子模块已经注册进去了。
访问刚刚新创建的服务信息提供接口
控制台打印出 微服务信息
页面返回当前服务信息
三、Eureka 自我保护机制
3.1 概述
保护模式主要用于一组客户端和 Eureka Server 之间存在网络分区场景下的保护。一旦进入保护模式,Eureka Server 将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据,也就是不会注销任何的微服务。
如果出现在 Eureka Server 可视化页面中出现以下内容,即说明 Eureka Server 进入保护模式
自我保护机制,简单来说就是 某一时刻注册进 Eureka Server 中的某一微服务不可用了,Eureka Server 不会立即清理,依旧会保存该服务的信息,这属于CAP定理中的 AP分支,即 可用性(Availability)和分区容错性(Partition Tolerance)。
3.2 为什么会产生 Eureka 自我保护机制?
为了防止 Eureka Client 在正常运行的情况下,因为与 Eureka Server 存在网络不通的情况下,Eureka Server 不会立刻将 Eureka Client 服务删除。
3.3 什么是自我保护模式?
默认情况下,如果 Eureka Server在一定时间内没有收到来自某一微服务实例的心跳(默认90秒),Eureka Server 将会立即注销该实例,但是当网络分区故障发生延迟、卡顿、拥挤等情况时,微服务与 Eureka Server 之间就会出现无法正常通信,以上行为可能就会导致 Eureka Server将该微服务信息移除,这就是一个很危险的行为,因为当前微服务实际是健康正常运行的,此时本不应该注销该服务。Eureka 通过“自我保护模式”来解决这个问题,即当 Eureka Server 节点在短时间内丢失过多的客户端时,Eureka 判断此时可能发生了网络分区故障,那么这个节点就会进入自我保护模式。
在自我保护模式中,Eureka Server 会保护服务注册表中的信息,不在注销任何服务实例。它的设计哲学就是宁可保留错误的服务注册信息,也不盲目注销任何可能健康的服务实例。
综上,自我保护模式是一种应对网络异常的安全保护措施。它的架构哲学是宁可同时保留所有微服务(健康的微服务和不健康的微服务都会保留),也不盲目的注销任何微服务。使用自我保护模式,可以让 Eureka 集群更加的健壮、稳定。
3.4 怎么禁用自我保护
3.4.1 打开 Eureka注册中心中的 application.yml ,增加关闭相关配置信息
server:
port: 7001
eureka:
instance:
#hostname: localhost #单机版 eureka 服务端实例名称
hostname: eureka7001.com #集群版 eureka 服务端实例名称
client:
register-with-eureka: false #false 表示不向服务中心注册自己
fetch-registry: false #false 表示自己就是注册中心,职责就是维护服务实例,并不需要去检索服务
service-url:
#defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #单机版
defaultZone: http://eureka7002.com:7002/eureka/ #设置与Eureka Server 交互的地址查询服务和注册服务都需要依赖这个地址
server:
enable-self-preservation: false #true-开启自我保护机制,不会删除不可用服务;false-关闭自我保护机制,保证不可用服务被及时剔除,默认为true
eviction-interval-timer-in-ms: 2000 #Eureka 客户端向服务端发送心跳的间隔时间,单位:毫秒(默认是30秒)
修改完后,重启 Eureka 服务,并刷新 Eureka Server 可视化界面,看到如下信息,即成功关闭自我保护模式。
3.5 自定义 Eureka Client 向 Eureka Server 发送心跳频率
打开支付子模块 cloud-provider-payment8001中的 application.yml 配置文件,增加相关配置