spring-cloud / spring-cloud-consul

Spring Cloud Consul
http://cloud.spring.io/spring-cloud-consul/
Apache License 2.0
813 stars 541 forks source link

dependency cycle when Use my own ConsulServiceRegistry with spring-boot-starter-actuator #831

Open c1emon opened 1 year ago

c1emon commented 1 year ago

When consul set with discovery.heartbeat.enabled=true and spring-boot-starter-actuator's health endpoint enabled.

At same time, spring-boot-starter-data-mongodb also added. Use my own ConsulServiceRegistry.

Startup and comes with dependency cycle for consul's TtlScheduler! Here is my example with logs, spring_consul_err.

ghimisradu commented 1 year ago

I'm having the same issue, but without overriding anything from consul, just having spring-cloud-starter-consul-discovery, spring-boot-starter-actuator and spring-boot-starter-data-mongodb-reactive on the same classpath and enabling the spring.cloud.consul.discovery.heartbeat.enabled=true. Here's a reproduction project

gc-garcol commented 11 months ago

in heartbeat, set use-actuator-health to false

        heartbeat:
            use-actuator-health: false
            enabled: true

You can check the ConsulHeartbeatAutoConfiguration to find out the issue

@ConditionalOnProperty(value = "spring.cloud.consul.discovery.heartbeat.use-actuator-health", havingValue = "true",
            matchIfMissing = true)
    static class ActuatorBasedApplicationStatusProviderConfig
chillb0nes commented 10 months ago

Startup and comes with dependency cycle for consul's TtlScheduler! Here is my example with logs, spring_consul_err.

Copying the cycle here for clarity

***************************
APPLICATION FAILED TO START
***************************

Description:

The dependencies of some of the beans in the application context form a cycle:

   stationController defined in file [/Users/clemon/Downloads/demo/build/classes/java/main/com/example/demo/station/StationController.class]
┌─────┐
|  mongoTemplate defined in class path resource [org/springframework/boot/autoconfigure/data/mongo/MongoDatabaseFactoryDependentConfiguration.class]
↑     ↓
|  mappingMongoConverter defined in class path resource [org/springframework/boot/autoconfigure/data/mongo/MongoDatabaseFactoryDependentConfiguration.class]
↑     ↓
|  mongoMappingContext defined in class path resource [org/springframework/boot/autoconfigure/data/mongo/MongoDataConfiguration.class]
↑     ↓
|  consulAutoServiceRegistrationListener defined in class path resource [org/springframework/cloud/consul/serviceregistry/ConsulAutoServiceRegistrationAutoConfiguration.class]
↑     ↓
|  consulAutoServiceRegistration defined in class path resource [org/springframework/cloud/consul/serviceregistry/ConsulAutoServiceRegistrationAutoConfiguration.class]
↑     ↓
|  commonConsulServiceRegistry defined in class path resource [com/example/demo/consul/CommonConsulAutoConfiguration.class]
↑     ↓
|  ttlScheduler defined in class path resource [org/springframework/cloud/consul/support/ConsulHeartbeatAutoConfiguration.class]
↑     ↓
|  actuatorHealthStatusProvider defined in class path resource [org/springframework/cloud/consul/support/ConsulHeartbeatAutoConfiguration$ActuatorBasedApplicationStatusProviderConfig.class]
↑     ↓
|  healthEndpoint defined in class path resource [org/springframework/boot/actuate/autoconfigure/health/HealthEndpointConfiguration.class]
↑     ↓
|  healthContributorRegistry defined in class path resource [org/springframework/boot/actuate/autoconfigure/health/HealthEndpointConfiguration.class]
↑     ↓
|  mongoHealthContributor defined in class path resource [org/springframework/boot/actuate/autoconfigure/data/mongo/MongoHealthContributorAutoConfiguration.class]
└─────┘

Here is my analysis:

WebServerInitializedEvent is the only event type that consulAutoServiceRegistrationListener can process, so It should be enough to explicitly declare it in bean definiton to fix this issue. Either by changing implements SmartApplicationListener to implements ApplicationListener<WebServerInitializedEvent> or annotating onApplicationEvent method with @EventListener(WebServerInitializedEvent.class).

Unfortunately I don't have time to test this hypothesis, but I would be glad if someone could do it and submit a PR if everything works fine.