How to implement Microservices Architecture – Configuration Management

Share with friends

Reading Time: 6 minutes

Why and how to externalize configuration in a distributed (Microservices) system?

We need a central place to manage external properties for all Microservices across all environments. How we can implement it using Spring Cloud Config.

This is the second article on the microservices implementation and we will discuss the details of config server and config client implementation. Please go to Microservices Overview if you would like to read more about microservices and looking for other distributed pattern implementation.

We are going to implement the config server, please see the orange box ( Config Server+Git Repo) in the below diagram.

configuration management, spring cloud config, microservices
Microservices Configuration Management

What are the options to externalize configuration-

  1. Property file –  All config settings are part of local property files of the application. This approach is not feasible in distributed scenarios because different applications need to share the config settings.
  2. Database – Distributed application can share the settings using this approach but we can’t maintain the revision history and will be very hard to track the changes.
  3. Spring cloud config – Provides server and client application for externalized configuration in a distributed system.

What is Spring cloud config-

It provides Http access to git or file-based configurations. This application can be accessed from any application using HTTP protocol to retrieve the configuration settings.

Below are the steps to create a config server using Spring Cloud Config-

Spring cloud config server can read the values from local property file or from the GitHub and it caches the values. There are three basic steps to create it-

  1. Build the Spring project
  2. Choose a config source
  3. Add a config file

Step 1 – Build the Spring Project

  • Create a Spring Starter project using Spring STS or any other IDE
Spring Cloud Config
Spring Boot Starter Project
  • Add spring-cloud-config-server and spring-cloud-actuator POM dependency
Spring Cloud Config
POM Dependency
  • Add @EnableConfigServer annotation to the main class to enable the config server
Spring Cloud Config
ConfigServerAnnotation

Step 2 – Choose a config source

There are two options –



Step 3 – Add a config file

You can add any format text file like JSON, YML, property file and it also supports nested folders structure. We will first implement it using local file (section 3.A) and then Git based (Section 3.B ) config server.

3. A)  Let’s first implement using local file-

  • First, add a config folder in the src/main/resources folder.
  • Add local properties files like demo1.properties, demo2.properties, and demo3.properties in the config folder.
  • Next, add configuration in the properties files  like message=demo1, message=demo2, and message=demo3
  • And, add below properties in the application.properties to configure the application.

server.port=8888
spring.profiles.active=native  (this will tell spring cloud config to use the local config files)

  • You can test this config server based on local file using browser, just open the below URL and you should see the property message and its value like below-

Scenario 1 – http://localhost:8888/demo1/default

{"name":"demo1","profiles":["default"],"label":null,"version":null,"state":null,"propertySources":[{"name":"classpath:/config/demo1.properties","source":{"message":"demo1"}}]}

Scenario 2 – http://localhost:8888/demo2/default

{"name":"demo2","profiles":["default"],"label":null,"version":null,"state":null,"propertySources":[{"name":"classpath:/config/demo2.properties","source":{"message":"demo2"}}]}

Scenario 3 – http://localhost:8888/demo3/default

{"name":"demo3","profiles":["default"],"label":null,"version":null,"state":null,"propertySources":[{"name":"classpath:/config/demo3.properties","source":{"message":"demo3"}}]}

You can download and play with this version of code from GitHub link https://github.com/manishsingh27/microservices-config/tree/DemoConfigServerBasedOnLocalFile

3. B)  Now implement the config server using GIT-

  • Create a new repository in your GitHub account, you can download config repo from https://github.com/manishsingh27/microservices-config-settings GitHub link.
  • In this repo, default application file is application.properties and there is two subfolder domo1 and demo2. Default file for demo1 is  demo1.properties and for demo2 is demo2.properties. I also added files for dev and QA environment, we will access these files properties using spring config server.
microservices-config-settings-GitHub-repo
  • Update application property file to point to GitHub repo. Comment the spring.profiles.active=native property and add a new property to point to GitHub repo like –

spring.cloud.config.server.git.uri=https://github.com/manishsingh27/microservices-config-settings.

You can also use username and password for private repo.

  • And add the search path like below otherwise config server will always return the default value from the application.property file.

spring.cloud.config.server.git.search-paths=demo*

  • Now it is ready for testing, let’s validate the various scenarios using Postman. There are three sections of the URL, /{applicationName}/{profile}[/{lable}] where label is optional.

Scenario 1   – No app or profile match – Config server will return default property values using application.properties file, for e.g.

http://localhost:8888/dummyappname/dummyprofilename URL will return response-

{
 "name": "dummyappname",
 "profiles": [
 "dummyprofilename"
 ],
 "label": null,
 "version": "487d07b8774a94c9f08d68bec2c786217232fb08",
 "state": null,
 "propertySources": [
 {
 "name": "https://github.com/manishsingh27/microservices-config-settings/application.properties",
 "source": {
 "demo.prop": "default-value"
 }
 }
 ]
}

Scenario 2 – Subfolder default value – Submit request to http://localhost:8888/demo1/default using Postman, it should return default properties values from demo1 folder and application.properties files like below-

{
 "name": "demo1",
 "profiles": [
 "default"
 ],
 "label": null,
 "version": "487d07b8774a94c9f08d68bec2c786217232fb08",
 "state": null,
 "propertySources": [
 {
 "name": "https://github.com/manishsingh27/microservices-config-settings/demo1/demo1.properties",
 "source": {
 "demo.prop": "demo1-default-value"
 }
 },
 {
 "name": "https://github.com/manishsingh27/microservices-config-settings/application.properties",
 "source": {
 "demo.prop": "default-value"
 }
 }
 ]
}

Scenario 3 – Subfolder profile value – Just add the profile name instead of the default, it will return folder profile, folder default and app default values, for e. g. http://localhost:8888/demo1/dev

{
 "name": "demo1",
 "profiles": [
 "dev"
 ],
 "label": null,
 "version": "487d07b8774a94c9f08d68bec2c786217232fb08",
 "state": null,
 "propertySources": [
 {
 "name": "https://github.com/manishsingh27/microservices-config-settings/demo1/demo1-dev.properties",
 "source": {
 "demo.prop": "demo1-dev-value"
 }
 },
 {
 "name": "https://github.com/manishsingh27/microservices-config-settings/demo1/demo1.properties",
 "source": {
 "demo.prop": "demo1-default-value"
 }
 },
 {
 "name": "https://github.com/manishsingh27/microservices-config-settings/application.properties",
 "source": {
 "demo.prop": "default-value"
 }
 }
 ]
}

How to get formatted response like JSON-

If you are looking for the response in property, YML or JSON format, you have to just change the URL and config server will return the response in that format so that you can consume from the client app.

http://localhost:8888/demo1-default.properties

http://localhost:8888/demo1-default.yml

http://localhost:8888/demo2-dev.json

{
 "demo": {
 "prop": "demo2-dev-value"
 }
}

You can download the source code from GitHub and play with it, link is here https://github.com/manishsingh27/microservices-config/tree/DemoConfigServerBasedGitHub

Client app – How to consume Config Server response

Now we need a client system to consume the response from the config server. We can develop client system in any language like Node.js or .NET to consume the response over HTTP. I am going to use Spring cloud config client because Spring client app uses config server as a property source and it has natively support to consume the response.

Step 1 – Create a Spring starter project and add Config Client and Web dependencies.

Step 2 – Add property file settings to retrieve the config values from Config Server-

2 A) application.property file change – Add config server app/folder name to retrieve the properties like below-
spring.application.name=demo1

2 B) bootstrap.properties file change –  Add this new file, it is required to set profile name and config server URL before application default settings activation-

Add config server profile name –
spring.profiles.active=default
Add Config server URL –
spring.cloud.config.uri=http://localhost:8888

Step 3 – Now add controller like below to fetch the values and test it using http://localhost:8080/v1/getPropValues URL.

@Value("${demo.prop}")
 String demoProp;
 
 @RequestMapping(value = "getPropValues", method = RequestMethod.GET)
 public String getDemoProp (final HttpServletRequest request) { 
 return "prop value is- " + demoProp;
 }

You can download the client app source code from GitHub and play with it, link is here https://github.com/manishsingh27/microservices-config-client-app/tree/configClientAppWithNoSecurity

Below are the GitHub link for all three apps, you can clone/download and play with these apps-


This Config Server is not secure and it can be accessed by anyone. My next article will be on config server security and we will secure the config server and its values.


Share with friends

Leave a Reply

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