Eureka 客户端未反映 OUT_OF_SERVICE 的手动状态

Eureka Client not reflecting manual status of OUT_OF_SERVICE

我有一个使用 Eureka 发现辅助应用程序的管理器应用程序。两者都在使用 Spring Cloud Netflix 和他们提供的自动配置来进行服务注册和发现。

经理有时会将一个实例标记为 OUT_OF_SERVICE,一段时间后(大约几分钟)将同一实例标记为 UP

管理器使用 CloudEurekaClient 发现实例,然后设置其状态:

@Autowired
private CloudEurekaClient cloudEurekaClient;

...

InstanceInfo instance = cloudEurekaClient.getNextServerFromEureka(WORKER_SERVICE_NAME, false);
cloudEurekaClient.setStatus(InstanceInfo.InstanceStatus.OUT_OF_SERVICE, instance);
// do some work
cloudEurekaClient.setStatus(InstanceInfo.InstanceStatus.UP, instance);

这似乎很有效。 Eureka 服务器状态页面显示我的实例从 UPOUT_OF_SERVICE:

然而,CloudEurekaClient 似乎不知道实例是 OUT_OF_SERVICE。相反,使用调试器,我发现该实例的状态为 UP 和 overridenStatus 为 UNKNOWN:

注意:如果我调用 cloudEurekaClient.getApplication("worker").getInstances() 它会显示 4 个 UP 实例,但没有提到 OUT_OF_SERVICE.

这是预期的吗?我假设尤里卡客户端会知道一个实例是 OUT_OF_SERVICE,但这不是我所看到的行为。这会导致我使用 CloudEurekaClient 显示 UPOUT_OF_SERVICE 实例数的健康指标出现问题。

经过一些挖掘,问题似乎是设置实例状态会立即调用 Eureka 服务器,这就是服务器状态 UI 实时显示正确状态的原因:

public void setStatus(InstanceStatus newStatus, InstanceInfo info) {
    getEurekaHttpClient().statusUpdate(info.getAppName(), info.getId(), newStatus, info);
}

但是,调用 CloudEurekaServer.getNextServerFromEureka() 使用本地缓存,该缓存仅在计时器上定期更新,计时器由 EurekaClientConfig.getRegistryFetchIntervalSeconds() 定义。

所以我处于竞争状态,如果我将实例状态设置为 OUT_OF_SERVICE 并尝试在刷新缓存之前查询应用程序的发现客户端,客户端和服务器有不同的视图实例。如果我在向客户端询问下一个服务器之前等待 registryRefreshInterval 秒,它会正确地忽略我手动放入 OUT_OF_SERVICE 状态的实例。