Centralizing Configurations with Spring Cloud Config

Bing Liu Microservices, Spring Boot, Technology Snapshot Leave a Comment

When the Microservices approach became popular a few years ago, many companies rushed to build their own microservices or to convert their legacy applications into microservices. Over the years, companies have implemented an abundance of microservices, mostly with Spring Boot. Each of them manage their own configurations across deployment environments like Dev, Test, and Prod.

Due to the nature of a complex business process, there are many common configurations (e.g. databases, queues, email servers, and FTP servers, etc.) used in the distributed services. This can result in services having redundant and confusing configs on a distributed system. It can become challenging to update the configs for too many services on a distributed system across multiple environments.

Thankfully, Spring Cloud Config provides the implementation to successfully resolve these issues. It 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 concepts on both client and server map identically to the Spring Environment and PropertySource abstractions, so they fit very well with Spring applications.

In this post, I’ll demonstrate Config Server and Client with example code. I’ll show you how to use Git or a local repository as a central place to store all the config files. The diagram below illustrates how the distributed client services (e.g. Investment Position/Price/Reporting Data service) fetch their configuration from the Config Server, which in turn retrieves them from one central place.

1. Configuring Spring Cloud Config Server

Spring Cloud Config Server provides an HTTP resource-based API for external configuration (name-value pairs or equivalent YAML content). It is a regular Spring Boot application with @EnableConfigServer annotation to standup a config server that can provide config to client services. You can view the complete server code here.

@SpringBootApplication
@EnableConfigServer     //  Spring Cloud annotation to make it config server
public class ConfigServerExampleApplication {
	public static void main(String[] args) {
		SpringApplication.run(ConfigServerExampleApplication.class, args);
	}
}

The Config Server needs to know which config repository to manage. See Section 3: Configuring a Backend To Store Config Files. In this example, the default Git repository is used.

See Also:  Quick Start: AWS SQS + Spring Boot Processing FIFO Queues

Application.yml (Git as config store)

server:
   port: 8888
spring:
   cloud: 
      config:
         server:
           git:          
             uri: https://github.com/in-the-keyhole/spring-cloud-configuration
             search-paths: 
              - '*ConfigrationFiles'

Application.yml (System file as config store)

server:
   port: 8888
spring:
  profile:
      active: native
   cloud: 
      config:
         server:
           native:          
             searchLocations: file\\\<configFileLocations> 

By default, Config server uses port (8888). A client application by default calls the local config server on port 8888 to fetch its properties. Here is a sample request from a client application to a config server to fetch its properties for test environment.

2. Configuring Spring Cloud Config Client

A Spring Boot application can be easily configured as the Config Client to read configuration from the config server (e.g. http://localhost:8888). Spring Cloud provides org.springframework.cloud:spring-cloud-starter-config dependency to connect to Config Server. Add this to pom.xml. You can dins the client source code here.

The properties to configure the Config Client must be read in before the rest of the application’s configuration is read from the Config Server, during the bootstrap phase. Which is in this case, the property file is investment-position-config in Git.

bootstrap.yml

spring:
  application:
      name: investment-position-config   
  cloud:
    config:
       uri: http://localhost:8888   

application.yml: The properties can be accessed in multiple environments (dev, test, prod, etc.) If the client service is compiled in test, for example, it will pull only the properties of test environment.

spring:
  profiles:
    active: test
server:
  port: 8081

Test the example Config Client to access Config Server to get config stored in Git. (Note: it retrieves the test profiles in investment-position-config.yml.)

@RestController
public class ConfigClientController {

	@Value("${position.price.queue}")
	private String positionPriceQueueName;

	@Value("${position.price.notification.sendTo}")
	private String positionNoteSentTo;

	@RequestMapping("/showClientConfigs")
	@ResponseBody
	public String showClientConfigs() {

		return "Generic Price Queue Name : " + positionPriceQueueName +
				"
 Notification Email Address (TEST) : " + positionNoteSentTo;
	}
}

By default, the configuration values are read on the client’s startup and not again. You can force a bean to refresh its configuration (that is, to pull updated values from the Config Server) by annotating the ConfigClientController.java with the Spring Cloud Config @RefreshScope and then triggering a refresh event.

@RestController
@RefreshScope
public class ConfigClientController {

	@Value("${position.price.queue}")
	private String positionPriceQueueName;

	@Value("${position.price.notification.sendTo}")
	private String positionNoteSentTo;

	@RequestMapping("/showClientConfigs")
	@ResponseBody
	public String showClientConfigs() {

		return "Generic Price Queue Name : " + positionPriceQueueName +
				"
 Notification Email Address (TEST) : " + positionNoteSentTo;
	}
}

3. Configuring A Backend To Store Config Files

Config files are managed by Cloud Config Server. There are two ways to store them in a central place listed below. Either way, Config Server doesn’t need restart when there is an update in these config files. However, the Config Client services do need a restart to get their updated properties. One additional benefit to storing in a Git repository is that any change can rollback if there is an error. By default, Spring Cloud Config uses a Git backend.

  • Store configurations on the local of its server as system files
  • Use GIT or SVN repository
See Also:  Elm Language

Property keys in more specifically name files overrides those in application.yml. Click here to view the complete example config files in Git.

Conclusion

I hope you now have a better understanding of how Spring Cloud Config works with this example. If you are interested in this technology, you can explore it further or customize it to your business needs. The source can be downloaded from the links below.

https://github.com/in-the-keyhole/spring-cloud-config-server-example
https://github.com/in-the-keyhole/spring-cloud-config-client-example
https://github.com/in-the-keyhole/spring-cloud-configuration

What Do You Think?