DEV Community

Marcin Piczkowski
Marcin Piczkowski

Posted on • Updated on

Spring Cloud step-by-step (part 3)

This is a continuation of previous blog posts:

Source code for this part can be found at GitHub in spring-cloud-3 branch.

Let's say we don't want to hardcode the URL to Config Service in our application properties because it may change from environment to environment.
Of course, we could pass this property as JVM environment variable on each environment, but then we need to worry about it in application startup scripts.
Instead, we could use service registry (such as Netflix Eureka) and only use a friendly name for a service, instead of its URL.

Here we will update Config Service and Pricing Service applications to use service discovery mechanism with Spring Cloud Discovery.

Configuring Eureka Server

Similarly, like we configured Config Service we will configure Eureka Server.
We can generate Config Service app with Spring Initializr at http://start.spring.io again.

All we need is to choose "Eureka Server" and "Web" from dependencies.

Generate project

This would generate app with maven dependencies in pom.xml:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

Then we need to enable discovery server with annotation on main class:

@EnableEurekaServer

and configure Eureka Server to not try to connect to itself - add resources/application.yalm with content:

server:
  port: ${PORT:8761}

eureka:
  client:
    registerWithEureka: false
    fetchRegistry: false
    server:
      waitTimeInMsWhenSyncEmpty: 0

Configuring Eureka clients

In Pricing Service and Config Service we need to add a dependency

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

and add Eureka client autoconfiguration with annotation

@EnableEurekaClient 

Note the fact that in some examples in the web you may find annotation @EnableDiscoveryClient which basically does the same if you have Eureka dependencies in the classpath, but it has subtle difference.
There are multiple implementations of Discovery Service in Spring Cloud, such as Eureka, Consul, Zookeeper.

@EnableDiscoveryClient lives in spring-cloud-commons and chooses the implementation from the classpath.

@EnableEurekaClient lives in spring-cloud-netflix and only works for Eureka.

Once we have an annotation on main class, when we start the app, it will try to contact the Eureka server on http://localhost:8761 (the default value of eureka.client.serviceUrl.defaultZone)

Now start Eureka Service and Config Service and go to Eureka console at http://localhost:8761

You would see an UNKNOWN service in the registry.

Eureka dashboard

This is because we have not specified Config Service name.

In Config Service create file resources/bootstrap.properties and add property:

spring.application.name=config-service

This is a similar property to the one which we have added in Pricing Service bootstrap.properties and this is how Spring Cloud allows identifying a service by name.

We could actually add this property in application.properties and in this case it would still work but there are cases when the name is required yet before application context starts to initialize
and bootstrap.properties is the one which is loaded at very first place when application starts so it's safer to put spring.application.name already there.

Now when we restart Config Service it will be named in Eureka dashboard list.

Similarly, we can configure Pricing Service with Eureka.

We need to add the same dependencies as we added in Config Service, then @EnableEurekaClient annotation on main class.

Pricing Service already has spring.application.name property configured before.

What is left is to replace hard-coded URL to Config Service with Eureka discovery.

Before we added Eureka we had such configuration in Pricing Service bootstrap.yaml:

spring:
  application:
    name: pricing-service
  cloud:
    config:
      uri: http://localhost:8888

Even though we added Config Service registration in Eureka, by default it does not affect other services which use Config Service.
We have to explicitly tell that we want to use Eureka client library to discover Config Service by setting property spring.cloud.config.discovery.enabled=true in Pricing Service bootstrap.yaml.

Spring documentation states:
The price for using this option is an extra network round trip on startup to locate the service registration. The benefit is that the Config Service can change its coordinates, as long as the Discovery Service is a fixed point.

Eureka client will try to find service named configserver in Eureka registry, but won't find such, as we named Config Service differently by setting the property spring.application.name=config-service in Config Service bootstrap.yaml.

Then we have to explicitly define the name of Config Service in Pricing Server bootstrap.properties. The final configuration will look as follows:

spring:
  application:
    name: pricing-service
  cloud:
    config:
      discovery:
        enabled: true
        service-id: config-service

When we start Pricing Service we should see a log like:

c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://192.168.43.107:8888/

It means Eureka client managed to resolve the location of Config Service.

It was handled automagically by Spring, but we have not seen how to call other services manually from java code (e.g. with RestTemplate).

I will explain how to do it in next post soon.

Top comments (2)

Collapse
 
nabilgasri profile image
nabilgasri

Hi Marcin, thakyou for your serie.
For the part 3 You mean use @EnableEurekaServer and not @EnableConfigServer for the discovery server :).

Collapse
 
piczmar_0 profile image
Marcin Piczkowski

Hi, I'm glad you liked it. Thanks for spotting this out. I have already corrected. You're right, it should be as in the source code - @EnableEurekaServer.