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

UPDATE

此repo中的README已更新,以在接受的答案中演示解决方案。


我正在使用基于本指南的Spring Boot Eureka服务注册和发现的简单示例。

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

但是,如果我启动两个具有相同名称的实例,则仪表板仅显示1个正在运行的实例,而DiscoveryClient仅显示第二个实例。

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

以下是我正在采取的步骤以及我所看到的步骤的更多细节:

尤里卡服务器

启动服务器

 cd eureka-server mvn spring-boot:run 

访问位于http:// localhost:8761的Eureka仪表板

请注意,尚未注册“实例”

尤里卡客户

启动客户端

 cd eureka-client mvn spring-boot:run 

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

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

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

/instances端点最多需要一分钟才能更新,但最终应显示已在Eureka Discovery Client中注册的所有eureka-client实例。

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

您现在也可以再次访问Eureka dashoboard并在那里看到它。

使用其他名称启动另一个客户端

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

 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上运行的实例,但由于某种原因,它不显示在端口8080上运行的实例。

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

Eureka仪表板仅显示1个eureka-client运行实例。

这里发生了什么?

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

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

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

问题是,为什么我们不能同时看到两个eureka-client实例?

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

我不建议将其用于AWS部署,因为使用instanceId会导致您无法确定哪台计算机托管特定服务 – 另一方面我怀疑您将在一台计算机上托管两个相同的服务,对吧?

通过在Eureka配置文件中设置唯一的euraka.instance.hostname,可以在管理门户中显示所有实例。

主机名用作在com.netflix.discovery.shared.Application中存储InstanceInfo的密钥(因为没有设置UniqueIdentifier)。 所以你必须使用独特的主机名。 在此方案中测试function区时,您会看到负载不会平衡。

以下是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之前的一个错误,您可以在https://github.com/codecentric/spring-boot-admin/issues/134查看更多信息。