How it works...

With a seemingly effortless change, we have switched one service discovery provider, Consul, for another, Eureka. What looked like not much of a change on the outside actually did quite a bit of work under the hood. The reason we were able to do it so easily is the common set of APIs provided by the spring-cloud-commons and spring-cloud-context foundational libraries. Automated module loading support via the spring.factores descriptor allowed for transparent substitution in the initialization of a different service discovery provider. As long as we retained the @EnableDiscoveryClient annotation on our BookPubApplication class, Spring Cloud did the heavy lifting, taking care of loading the appropriate autoconfiguration files and setting up all the right beans to get our application working with Eureka.

We had to remove the Consul dependency from our classpath at the very first step of the recipe, and that had to be done in order to disambiguate the DiscoveryClient implementation. Without doing so, our application context would have ended up with two different implementations of the DiscoveryClient interface, which in itself would not be bad, except that Spring Cloud would have to disambiguate and choose one, and might not choose the one we want.

If we leave the spring-cloud-starter-consul-all dependency in our build.gradle file, and attempt to run the application, it will fail during startup and in the logs we will see the following entry:

WARN 5592 --- [  restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jmxMBeanExporter' defined in class path resource [org/springframework/boot/actuate/autoconfigure/endpoint/jmx/JmxEndpointAutoConfiguration.class]: Invocation of init method failed; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.cloud.client.serviceregistry.ServiceRegistryAutoConfiguration$ServiceRegistryEndpointConfiguration': Unsatisfied dependency expressed through field 'registration'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.cloud.client.serviceregistry.Registration' available: expected single matching bean but found 2: eurekaRegistration,consulRegistration  

As you can see from the exception, Spring autowiring can't decide which one of the service registries should be used. This is because both Eureka and Consul automatically have created an instance of Registration, and the autowiring wants only one.

Since there is a hard requirement for only having one registry, it is best not to configure multiple discovery client dependency libraries to avoid errors. If, for some reason, multiple libraries have to reside in the classpath, one should use configuration properties to explicitly enable/disable a specific client implementation. For example, both Consul and Eureka provide configuration to toggle the state. We can set spring.cloud.consul.discovery.enabled=true and eureka.client.enabled=false in application.properties if we prefer to use Consul to provide service discovery functionality.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.220.120