Eureka 开发随笔

Eureka 中服务发现过慢的问题如何解决

核心配置说明

  • Eureka Client(服务提供者)默认每 30 秒 向 Eureka Server 发送一次心跳,用于维持服务实例的租约。
  • Eureka Client(服务消费者)默认每 30 秒 从 Eureka Server 拉取一次最新的服务注册表(Registry)。
  • Eureka Server 默认每 60 秒 扫描一次服务注册表,以检测各服务实例的租约(心跳)状态。
  • 如果某个 Eureka Client(服务提供者)在 90 秒内未发送心跳,Eureka Server 会认为该服务实例已下线,并将其从服务注册表中剔除。

核心配置示例

为了解决 Eureka 中服务发现过慢的问题,可以调整以下配置参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Eureka Client 向 Eureka Server 发送心跳(续约)的时间间隔,单位秒,默认 30 秒
eureka.client.leaseRenewalIntervalInSeconds = 30

# Eureka Client 拉取服务注册表(Registry)的时间间隔,单位秒,默认 30 秒
eureka.client.registryFetchIntervalSeconds = 30000

# Eureka Server 定时清理过期服务实例的扫描时间间隔,单位毫秒,默认 60000ms(60 秒)
eureka.server.evictionIntervalTimerInMs = 60000

# Eureka Server 判定服务实例失效的时间(超过该时间未收到心跳则认为服务实例已下线),单位秒,默认 90 秒
eureka.instance.leaseExpirationDurationInSeconds = 90

# Eureka Server 更新响应缓存(Response Cache)的时间间隔,单位毫秒,默认 30000ms(30 秒)
eureka.server.responseCacheUpdateIntervalMs = 30000

Eureka 适当调整以上配置参数后,服务发现的时效性可以变成秒级,几秒钟就可以感知服务的上线和下线。

Eureka Server 更新响应缓存的说明

Eureka Server 内部实现了两级缓存机制,包括 ReadWrite Cache 和 ReadOnly Cache。其中,ReadWrite Cache 作为读写缓存,用于保存最新的服务注册表数据;ReadOnly Cache 作为只读缓存,主要用于对外提供服务注册表查询,以提高读取性能。两级缓存之间通过定时任务进行数据同步,默认每隔 30 秒将 ReadWrite Cache 的数据同步到 ReadOnly Cache,该时间间隔可以通过 eureka.server.responseCacheUpdateIntervalMs 参数进行配置。需要注意的是,ReadOnly Cache 的更新并不是逐条进行增量同步,而是通过定时任务从 ReadWrite Cache 重新构建完整缓存,并以原子方式整体替换,从而保证缓存数据的一致性和读取效率。

集群节点均出现在 unavailable-replicas 下面

Eureka 搭建高可用集群,启动多个注册中心并访问 Eureka 的控制台界面后,节点均出现在 unavailable-replicas,查阅各类资料和测试,提供的方案如下:

  • (1) eureka.client.serviceUrl.defaultZone 配置项的地址,不能使用 localhost 或者内网/外网 IP,需要使用域名,DNS 解析请自行配置,也可以在本机的 /etc/hosts 里映射域名
  • (2) spring.application.name 要一致(默认不配置也可以)
  • (3) register-with-eureka 设置为 true(默认不配置也可以)
1
2
3
4
eureka:
client:
register-with-eureka: true
fetch-registry: true
  • (4) 配置 eureka.instance.hostname (好像看到过正常情况下 Eureka 会自动获取设备 Host,但各节点在同一机器下时请务必添加,注意各节点独立配置自己节点的 Host)
1
2
3
eureka:
instance:
hostname: host1
  • (5) 千折腾万折腾还是不好使的时候,请去掉下面这个参数或者改为 false(神坑),未找到官方原因
1
2
3
eureka:
instance:
prefer-ip-address: false

个人大概理解了一下,prefer-ip-address: true 表示不使用主机名来定义注册中心的地址,而使用 IP 地址的形式,而 defaultZone 中是以域名的方式向注册中心注册的(测试了下使用 IP 注册到备份节点不可识别),最终导致分片节点不能识别匹配(IP 地址与域名),而认为分片均处于不可达状态。