Microservices: Writing a centralized configuration microservice

Last month I went to a talk about Microservices at Pivotal SF.
As I commented previously (you can take a look here if interested), this was one of the talks with more useful content and easy to follow I have ever been to.

After that, I decided to tackle several points related to microservices development in Spring and how to do them with spring cloud. The code of the whole exercise can be found on github.

Decentralized configuration

When implementing microservices, you can go for isolating the configuration for each service into its own project. To instantiate a service, we would need several properties like:

  • Where the service is going to listen?
  • Where do we store the additional properties?
  • Do I need to communicate to other processes/services? If so, how do I connect to them without having hardcoded the information?

The following image can represent the decentralized configuration approach:

Microservices- Configuration decentralized

Microservices- Configuration decentralized

The main issues, as reflected on the picture above are:

  • Maintainability of configuration
  • Inconsistency on properties
  • Dynamic property refresh on microservices
  • Each microservice deals with the configuration: duplication of code, no flexibility, etc…

Centralized configuration

Solving the issue of configuration inconsistency and maintainability on distributed systems and to act as a main point for configuration , we could go for the option of having a microservice for providing the configuration to the rest of the services.

Microservices - Configuration centralized

Microservices – Configuration centralized

 

Hands on code

In the following sections we will code a couple of services that pull information from a configuration microservice. After that, we will proceed to test and mention some of the extra benefits we could get going this route.

The overall architecture will be the following:

Microservices- Configuration service architecture

Microservices- Configuration service architecture

For convenience, all our services will be Spring Boot applications.

Step 1: Configuration service

As both services depend on the configuration service, we will proceed to implement this one first. Main thing to have in mind is to incorporate the artifact spring-cloud-config-server and use @EnableConfigServer on your configuration file.

Dependencies

The following dependencies need to be added to your pom:

Application

In order to be a configuration microservice, we need to add the annotation @EnableConfigServer

Once we have the main setup, we need to specify how we are going to get the properties. These are ideally loaded from a distributed environment (zookeeper, git or your custom one). For this case, git is the one that requires no additional setup to test.

Properties

For pointing to a git repository or configuration we can specify the property spring.cloud.config.uri. For our case, we are just going to use the same repository where this code is. The properties to be set are:

  • Port where the configuration server is going to expose the services
  • Properties for the service A
  • Properties for the service B

On this project we will add the properties under src/main/resources:

File: src/main/resources/application.properties

File: src/main/resources/config/svca-service.properties

File: src/main/resources/config/svcb-service.properties

Deployment

Once done these steps, we are able to run the configuration service.

Test

For checking the properties, you could hit the following endpoints:

  • http://localhost:8888/svca-service/master
  • http://localhost:8888/svcb-service/master

Also, in order to test that it dinamically refreshes the information, you could change some of the properties and hit the necessary endpoint. The new configuration should be updated.

Benefits

Being able to centralize the configuration makes us forget about configuration on the rest of the services. Being able to refresh the properties gives us possibilities like A/B testing and rollout of new features without having downtime and being able to control which features are exposed at any moment.

 

Step 2: Writing Services that consume the configuration microservice

For this step, we will proceed to give the details for building serviceA, although the same steps are for service B.

Dependencies

As the configuration service, we will need also to use the spring-cloud-starter-config artifact. It is a good idea to use the actuator one as well (spring-boot-starter-actuator)

Application

The main application is a normal Spring Boot setup. The configuration to access the configuration service will be exposed through the properties.

In order to see if we are getting the configuration, we could use a rest controller using one of the properties (name):

Note the annotation @RefreshScope. This annotation will make the bean to be refreshed when the enpoint /refresh is called (provided by actuator).

Properties

As the service is initialized with properties coming from the configuration service, application.properties is not longer valid. Spring boot project determines the properties required in order to connect to the configuration service should be exposed on src/main/resources/bootstrap.properties:

Note the property spring.application.name value. This property will indicate comprar generico viagra where to have a look inside the configuration service. This, along with the other property, will make the service to pull configuration from
http://localhost:8888/svca-service/master

Deployment

Just deploy the services as Spring Boot apps. My personal preference is through the command line with:

Note that, in order to deploy them, you should have the configuration service up and running on http://localhost:8888

Step 3: Test the infrastructure

In order to test the whole infrastructure make sure you have every service running. You could do that by running mvn spring-boot:run.

Endpoints to check

The following urls https://www.acheterviagrafr24.com/prix-du-viagra-en-pharmacie/ should be accessible:

Configuration service

  • Configuration of the service A: http://localhost:8888/svca-service/master
  • Configuration of the service B: http://localhost:8888/svcb-service/master

Service A

  • Endpoint for the health of the microservice: http://localhost:5000/health
  • Endpoint exposing the property from the config service: http://localhost:5000/info/name

Service B

  • Endpoint for the health of the microservice: http://localhost:7000/health
  • Endpoint exposing the property from the config service: http://localhost:7000/info/name

Testing dynamic properties

Let’s say we want to modify the name of the Service A. We would need to change the file src/main/resources/config/svca-service.properties under the configuration service project. After that, if we hit the configuration service:

http://localhost:8888/svca-service/master

We should be able to see the new property. However, if we hit the service A endpoint to see the information reflected, we cannot see any changes. The main reason is that calls over http are in general expensive; you don’t want to perform requests all time, only when necessary. Hence, the call to the configuration service is cached.

In order to refresh that property on the service to get the new property value from the configuration service, we need to hit the /refresh endpoint on the service:

This will tell us that the name property was changed and will force the bean to refresh.

In summary

  • We saw how we can move from a decentralized to a centralized configuration environment
  • Even when we are working with 3 services, things can get a bit messy. A kind of Address book for the cloud is necessary (Hint: Netflix released Eureka)
  • Having configuration centralized helped the way we get and access information, although we need to have into consideration strategies like caching between services.
  • In this example we saw the implementation with Spring Boot, although nothing stops you to combine different technologies. What I like about Spring Boot is that it is opinionated and normally designed by experts that are driving the industry. Their approach is quite flexible to anyone needs.
  • The possibility of being able to load configuration on the fly leads to way to more intelligent ways of A/B testing of feature release.

 

2 thoughts on “Microservices: Writing a centralized configuration microservice

Leave a Reply

Your email address will not be published. Required fields are marked *