从单个主机注册 Spring Boot Eureka Client 的多个实例

Register multiple Instances of a Spring Boot Eureka Client from a single host

更新

this repo 中的自述文件已更新,以在已接受的答案中演示解决方案。


我正在使用 Spring Boot Eureka 服务注册和发现的简单示例,该服务基于 this guide

如果我启动一个客户端实例,它会正确注册,并且可以通过 DiscoveryClient 看到自己。如果我用不同的名称启动第二个实例,它也能正常工作。

但是如果我启动两个同名的实例,仪表板只显示 1 个实例 运行,DiscoveryClient 只显示第二个实例。

当我杀死第二个实例时,第一个实例再次通过仪表板和发现客户端可见。

以下是有关我正在执行的步骤和所见所闻的更多详细信息:

尤里卡服务器

启动服务器

cd eureka-server
mvn spring-boot:run

http://localhost:8761

访问 Eureka 仪表板

请注意,'Instances' 尚未注册

尤里卡客户端

启动客户端

cd eureka-client
mvn spring-boot:run

直接访问客户 http://localhost:8080/

/whoami端点将显示客户端对其应用程序名称和端口的自知

{
  "springApplicationName":"eureka-client",
  "serverPort":"8080"
}

/instances 端点最多需要一分钟来更新,但最终应该会显示 eureka-client 的所有已在 Eureka Discovery 客户端注册的实例。

[   
    {
      "host":"hostname",
      "port":8080,
      "serviceId":"EUREKA-CLIENT",
      "uri":"http://hostname:8080",
      "secure":false   
    } 
]

您现在还可以再次访问 Eureka 仪表板,并在其中查看它。

启动另一个名称不同的客户端

您可以通过执行以下操作看到另一个客户端将被注册:

cd eureka-client
mvn spring-boot:run -Dspring.application.name=foo -Dserver.port=8081

/whoami 端点将显示名称 foo 和端口 8081

大约一分钟后,/instances 端点也将显示有关此 foo 实例的信息。

在 Eureka 仪表板上,现在将注册两个客户端。

使用相同名称启动另一个客户端

现在尝试通过仅覆盖端口参数来启动 eureka-client 的另一个实例:

cd eureka-client
mvn spring-boot:run -Dserver.port=8082

http://localhost:8082/whoami 端点显示了我们的预期。

大约一分钟后,/instances 端点现在也会在端口 8082 上显示实例 运行,但由于某种原因,它不会在端口 8082 上显示实例 运行端口 8080.

如果我们检查 http://localhost:8080 上的 /instances 端点,我们现在也只能看到 8082 上的实例 运行(尽管很明显,8080 上的那个是 运行 因为这就是我们的要求。

Eureka 仪表板仅显示 eureka-client 运行.

的 1 个实例

这是怎么回事?

让我们尝试在 8082 上终止 运行 实例,看看会发生什么。

当我们在8080上查询/instances时,它仍然只显示8082上的实例。

但一分钟后,它消失了,我们再次看到 8080 上的实例。

问题是,为什么我们看不到 eureka-client 的两个实例,而它们都是 运行?

对于本地部署,尝试在 eureka-client.properties 中 配置 {namespace}.instanceId 属性(或 eureka.instance.metadataMap.instanceId 以获取正确的 yaml Spring 基于云的设置的文件)。它深深植根于 Eureka 服务器计算应用程序列表和比较 PeerAwareInstanceRegistryImpl 的 InstanceInfo 的方式 - 当没有更多具体数据(例如:实例元数据可用)时,他们会尝试从主机名中获取 id..

不过,我不建议将它用于 AWS 部署,因为弄乱 instanceId 会给你带来麻烦,以确定哪台机器托管特定服务 - 另一方面,我怀疑你是否会在一台机器上托管两个相同的服务机器,对吧?

为了让所有实例都显示在管理门户中,请在您的 Eureka 配置文件中设置唯一 euraka.instance.hostname。

主机名用作在 com.netflix.discovery.shared.Application 中存储 InstanceInfo 的键(因为没有设置 UniqueIdentifier)。所以你必须使用唯一的主机名。在这种情况下测试功能区时,您会发现负载不平衡。

以下 application.yml 是示例:

server:
  port: ${PORT:0}

info:
  component: example.server

logging:
  level:
    com.netflix.discovery: 'OFF'
    org.springframework.cloud: 'DEBUG'

eureka:
  instance:
    leaseRenewalIntervalInSeconds: 1
    leaseExpirationDurationInSeconds: 1
    metadataMap:
      instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}}
    instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}}

之前在Eureka中的一个bug,你可以在https://github.com/codecentric/spring-boot-admin/issues/134

中查看更多信息