Centralize Configurations Using Spring Cloud Config

unsplash-logoAsh Edmonds

In This post we will Create Small POC for Spring Cloud Config and will use different Key Features of Spring Cloud Config.

The code for this post is available for download here. And Config files here

Problem
In a typical Microservices Architecture, We have Number of Small,Independent Services working together. Each service will have it’s own configurations in property files & we have multiple instances of each service. Now if we think about different environments like Development, Staging, and Prod etc It makes things more complicated.

Each time if we need to change the configuration of a microservice, we need go to the corresponding project, change its configuration and then restart the application for the change to take effect.
Managing These Configurations for multiple services across different environments becomes very critical
Spring Cloud Config provide Solutions to all these problems

What Is Spring Cloud Config ?

Spring Cloud Config provides server-side and client-side support for Externalized Configuration in a distributed system. With the Config Server, you have a central place to manage external properties for applications across all environments. The default implementation of the server storage backend uses git, so it easily supports labelled versions of configuration environments as well as being accessible to a wide range of tooling for managing the content. It is easy to add alternative implementations and plug them in with Spring configuration.

POC Application

Assume we have Small Application which includes two microservices Customer & Account. Customer service accepts email id of user and identifies if the user is Premium user or not. If the email id contains some keyword, then we will consider that customer as Premium Customer. At present we have defined the keyword in application.properties
e.g
For DEV - customer-service.emailtype=gmail.com
For QA - customer-service.emailtype=github.com
For DEV - customer-service.emailtype=microsoft.com

If I run http://localhost:8080/customer/niraj.sonawane@gmail.com in dev environment, I should get response as Premium Account.

Before Cloud Config
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

// Simple RestController which check if email has keyword or not.
@RestController
public class CustomerProfileController {
@Autowired
private CustomerServiceConfigurations customerServiceConfigurations;

@GetMapping("/customer/{email}")
public String getCustomerDetails(@PathVariable String email) {
if (email.contains(customerServiceConfigurations.getEmailtype())) {
return "Premium Account";
}
return "Free Account";
}
}
//Configuration Class For loading configs from application.properties.
//All properties starting with customer-service will be loaded in this class.
@Component
@ConfigurationProperties("customer-service")
@Data
public class CustomerServiceConfigurations {

private String emailtype;

}

//application.properties has below properties.
customer-service.emailtype=gmail.com

Before Cloud Config

Our Task is to externalize the Configurations in Git repository using Spring Cloud

After Cloud Config

Infographic vector created by freepik - www.freepik.com

1 Spring Cloud Config Server

Config Server acts as a sort of intermediary between our Spring applications and a typically version-controlled repository of configuration files. All microservices access properties files using config server.
We need to add <artifactId>spring-cloud-config-server</artifactId> dependency. And need to use @EnableConfigServer annotation.

Config Server
1
2
3
4
5
6
7
8
@SpringBootApplication
@EnableConfigServer
public class SpringCloudConfigServerApplication {

public static void main(String[] args) {
SpringApplication.run(SpringCloudConfigServerApplication.class, args);
}
}

Connecting Config Server to version-controlled repository

Spring Cloud Config Server supports Git,SVN, JDBC (relational database) etc as a backend for configuration properties.The default implementation of EnvironmentRepository uses a Git backend. For this POC will use git.We can also use File System based backend for configuration properties using native profile.

Config Server application.properties
1
2
3
spring.application.name=spring-cloud-config-server
server.port=8888
spring.cloud.config.server.git.uri=https://github.com/nirajsonawane/Spring-Cloud-Config-Server-Demo-Config-Repo.git

To Provide path of file based git system file://${user.home}/config-repo.

Run the config server and you should be able to access properties of customer-service at http://localhost:8888/customer-service/default
Similarly Account service properties will be available at http://localhost:8888/account-service/default

2 Config Client Configurations

To access Configurations through Config Server,Client applications needs to add
spring-cloud-starter-config dependency.
The properties to configure the Config Client must necessarily be read in before the rest of the application’s configuration is read from the Config Server, during the bootstrap phase.

Configure the Config server related properties in bootstrap.properties

bootstrap.properties
1
2
spring.application.name=customer-service
spring.cloud.config.uri=http://localhost:8888/

Now If we Start our Customer service, It will start accessing properties files from our config server. In logs we can verity this.
[ restartedMain] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at : http://localhost:8888/
And If we run http://localhost:8080/customer/niraj.sonawane@gmail.com I should get response as Premium Account. (Will access Default Profile)

3 Managing Profiles, Environment Specific properties

To manage environment specific properties, i.e. profiles add profile specific properties in repository. For customer-service we will add below files in our git repository.

  • customer-service-dev.properties
  • customer-service-prod.properties
  • customer-service-qa.properties

To set any specific profile we can use spring.profiles.active parameter in bootstrap.properties or using command line argument -Dspring-boot.run.profiles

Precedence rules for profiles are also the same as in a regular Spring Boot application: Active profiles take precedence over defaults, and, if there are multiple profiles, the last one wins (similar to adding entries to a Map).

4 RefreshScope

Until Now, We have Solved the problem of Centralizing the properties and managing different profiles. Now We will focus on how to update properties at run time without application Restart.

By default, the configuration values are read on the client’s startup, and not again. We can force a bean to refresh its configuration - to pull updated values from the Config Server - by annotating the Classes that are refering with the Spring Cloud Config @RefreshScope and then by triggering a refresh event.
There are other options are also available, I will cover them in next Post.

5 Useful Properties and Other Key Features

  • if client cannot connect to the Config Serve then use spring.cloud.config.fail-fast=true for fail fast.
  • Config Client can Retry if it is not able to connect, use spring.cloud.config.retry.*
  • SSL certificate can be disabled by setting the git.skipSslValidation property to true (default is false).
  • Timeout Can be set on Config server to read properties from git, Use git.timeout property
  • Multiple Repositories can be used by using Pattern Matching
  • Config Server supports the Encryption and Decryption of properties using JCE
  • Config Server supports DiscoveryClient implementation such as Eureka Service Discovery Config Server register with the Discovery Service.

The code for this post is available for download here. And Config files here

Share Comments