Version: Next

Eureka 自我保护

概述

  • 保护模式主要用于一组 客户端Eureka Server 之间存在 网络分区 场景下的保护
  • 一旦进入 保护模式Eureka Server 将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据,即 不会注销任何微服务
  • 如果在 Eureka Server 也面看到以下提示,则说明 Eureka 进入了 保护模式


  • 即:某时刻某个微服务不可用了,Eureka 不会立刻将其清理,依旧会对该微服务的信息进行保存,属于 CAP 中的 AP 分支 (先不管啥意思)

为什么会产生 Eureka 自我保护

  • 为了防止 Eureka Client 可以正常运行,但是 Eureka Server 网络不通畅的情况
  • 在这种情况下,我们希望 Eureka Server 不会立刻将 Eureka Client 服务提出,因为其并不是真的停止了,只是暂时失联

什么是自我保护模式

  • 默认情况下,Eureka Server微服务实例 之间维持心跳
  • 超过一定时间 Eureka Server 没有接收到 微服务实例 心跳,则将其实例注销(默认 90 秒)
  • 但当网络发生故障(如延时卡顿拥挤)时,微服务Eureka Server 之间无法正常通信,则以上机制存在弊端
    • 微服务实例 本身是健康的,此时 不应该将其注销
  • Eureka 通过 自我保护模式 来解决这个问题:
    • Eureka Server 节点在短时间内丢失过多客户端时,那么此 Eureka Server 节点就会进入自我保护模式
  • 《Spring cloud 与 Docker 微服务框架实战》

禁止Eureka自我保护

一旦微服务掉线,注册中心等待一端时间后将其删除

Eureka-Server7001

  • eureka-server-7001
  • 关闭自我保护:修改 YAML 文件,设置 eureka.server.enable-self-preservation=false
  • 修改心跳等待时间:设置 eureka.server.evication-interval-timer-in-ms=2000,失联 2000 毫秒就干掉
  • 恢复到 单机模式 方便测试
server:
port: 7001
eureka:
instance:
# hostname: localhost #eureka服务端的实例名称
hostname: eureka7001.com # 集群环境下,在hosts文件配置了自己地址的名字
client:
# false表示不向注册中心注册自己
register-with-eureka: false
# false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要检索服务
fetch-registry: false
service-url:
# 设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
# 单机
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
# 集群:使用定义在 hosts 里的名称,注册到对方节点
# defaultZone: http://eureka7002.com:7002/eureka/
server:
enable-self-preservation: false # 关闭 Eureka 自我保护
eviction-interval-timer-in-ms: 2000 # 失联 2 秒就把微服务干掉
  • 启动 7001 ,访问 localhost:7001
    自我保护模式已关闭。这可能导致在网络或其他故障时不能保护(微服务)实例

provider-payment8001

  • provider-payment8001
  • eureka.instance.lease-renewal-interval-in-seconds=30:Eureka 客户端向服务端发送心跳信号的时间间隔,默认为 30 秒,重新设置为 1
  • eureka.instance.lease-expiration-duration-in-seconds=90:Eureka 服务端在受到最后一次心跳后等待的时间上限,默认为 90 秒,超时则注册中心将微服务剔除,重新设置为 2
  • 恢复到 单机模式
server:
port: 8081
spring:
application:
name: cloud-payment-service
datasource:
username: root
password: root
url: jdbc:mysql://localhost:3306/springcloud?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
mybatis:
mapper-locations: classpath:mapper/*.xml
configuration:
map-underscore-to-camel-case: true #驼峰映射
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #调试打印SQL
eureka:
client:
#表示是否将自己注册进EurekaServer默认为true
register-with-eureka: true
#是否从EurekaServer抓取已有的注册消息,默认为true,单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetch-registry: true
service-url:
#集群版
#defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
#单机版 入驻到这个地址(就是注册中心地址)
defaultZone: http://127.0.0.1:7001/eureka/
instance: # 用来修改服务名称,防止暴露当前服务器主机
instance-id: payment8001
prefer-ip-address: true # 可以预览 ip 地址
lease-renewal-interval-in-seconds: 1 # Eureka 客户端向服务端发送心跳信号的时间间隔
lease-expiration-duration-in-seconds: 2 # Eureka 服务端在受到最后一次心跳后等待的时间上线

测试

  • 使用 Debug 启动 70018001 可以看到注册中心中已经注册了 8001 微服务


  • 故意关闭 8001 项目,可以看到注册中心立刻剔除 8001 微服务