简体   繁体   中英

Spring Cloud Config Server Circular Dependency With Netflix Eureka Discovery on Startup

I'm following this tutorial but I'm having some trouble figuring out the correct starting order of the services in order to get no errors (I need an error free response for my Docker swarm to initialize properly).

The order in which I'm starting the services is:

  1. config service : 8081 (spring cloud) <- tries to register with next
  2. discovery service : 8082 (eureka) <- gets its configs from previous
  3. API gateway service : 8080 (Zuul)
  4. book service : 8083 (example tutorial app)

If I go through the tutorial as written, I can't get past step 3.5 because the config server never registered with the discovery service. I did some digging around and found that the config server needs to have its main class annotated with @EnableEurekaClient in order for it to ping the discovery service periodically to register itself.

I then added this annotation in the code as follows:

@SpringBootApplication
@EnableConfigServer
@EnableEurekaClient /* this line was missing */
public class ConfigApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigApplication.class, args);
    }
}

and this to application.properties in the config service :

...
spring.application.name=config
# the following line was missing
spring.cloud.config.name=config
...

After doing so I was able to restart the config server and everything worked as expected because it registered itself with the discovery service which was already running when i restarted the config with my updated code.

When I shut down all services, and then attempted the same start order I listed in the beginning, I noticed that the config server is throwing a connection error every time it tries to register with the discovery service. This makes perfect sense to me since the discovery service is not yet running. The config server seems to be running fine despite this so when i continue execution of the rest of the services the app runs fine and the config server stops throwing errors once it realizes that a discovery service exists.

So my question is a 3 part:

  1. Is my assumption correct that the tutorial authors made a mistake in omitting the @EnableEurekaClient annotation and the spring.cloud.config.name registration from the tutorial?
  2. Is this error on config startup something i should just ignore because it resolves itself after the discovery service is back up and micro-service architecture allows services to come up and down?
  3. Is there a way to break the circular dependency where the discovery service depends on the config service which depends on the discovery service? I reduced the number of errors on config by increasing its refresh interval with eureka which delays the second ping till after eureka is up but i still get the 1 error on startup.

In the tutorial they have started a config server that exists with a static ip/port and does not attempt to find discovery. Then they launch the discovery service. This allows the discovery service to use the config from the static config server.

In the scenario, whilst the discovery service is running - the config server is restarted with new Eureka config that is introduced in step 3.4. The restarted config server will register itself with Eureka(you are right that the @EnableEurekaClient annotation is needed at this step). This allows other services to discover the config server by its server id rather than static ip/port.

There will be no errors in this scenario because the config server was started as a static service, that didnt attempt to initially register with discovery.

The problem you are experiencing is that you are trying to start everything up without going through that first step of creating a static config server so you will always get the initial register with eureka error.

If you absolutely must avoid that then you can do a few things:
You could keep the config server on a static ip/port and do not register it with eureka. This will require that you delete the following from your service configs:

spring.cloud.config.discovery.service-id=config
spring.cloud.config.discovery.enabled=true

and replace them with

spring.cloud.config.uri=http://static_ip:port

Another option is to keep Eureka on a static ip/port and define the config within its own application.properties (or yml) and delete the spring config dependency from its pom. Then your start order will be Eureka > config > other services. This will allow other services to identify the config server by id and eureka will not look for config externally.

Another option is to follow the tutorial with a slight tweak. Have a property in in the server config application properties called eureka.enabled=true

Create a EurekaConfig class with the annotation @ConditionalOnProperty(name="eureka.enabled")

@Configuration
@EnableEurekaClient
@ConditionalOnProperty(name="eureka.enabled")
public class EurekaConfig {
}

Now when it comes to starting your application for the first time use the command.

java -jar -Deureka.enabled=false path/to/config/server.jar

Then after eureka has started the config server can be killed and launched again with

java -jar path/to/config/server.jar

The first command will launch the config server without looking for eureka, the second will launch the config server that registers with eureka

In case using the @ConditionalOnProperty annotation doesn't work, there's another similar way you can try (I'm using Spring Boot 2.0.1) :

You can disable discovery client auto-register by setting property spring.cloud.service-registry.auto-registration.enabled to false in application.properties so that the config-server won't bother to register to Eureka as soon as it is up. You run the .jar file this way (specifying the property is optional as you've already done that in the properties file):

java -jar -Dspring.cloud.service-registry.auto-registration.enabled=false config-server.jar

Now start the Eureka server so that it fetches the configuration. And after that's done, kill the config-server and re-run it:

java -jar -Dspring.cloud.service-registry.auto-registration.enabled=true config-server.jar

And this time, the config-server will automatically register itself in Eureka.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM