Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
In this article, we will look over the Spring Cloud Config project which is one of the main projects under Spring Cloud and that’s mainly designed for centralizing the application configuration.
Spring Cloud Config is one of the main projects under Spring Cloud and that’s mainly designed for centralizing the application configuration which is one of the needs come up with the microservices world as stated in the Twelve-Factor App Manifesto.
In the microservices world, basically, each bounded context is implemented as separate microservices and scaled independently one from others. Briefly, that means numerous services each having its own configuration. And as you guess, management of these configurations manually and independently is a cumbersome work. For example, if a timeout value is to be increased then you must change the relevant property in all configurations of the deployed service; and worse, if the property is to be applied to several services that change may need to be applied to hundreds of configurations. That’s really quite awesome. You can think of this scenario using the following simple microservice arcitecture diagram.
So the config server solution comes to play to resolve this problem by the way of keeping all the configuration in one place and serving them to all services on demand.
That means centralizing all the application configuration in one place and that again means changing a configuration property would be applied once in the data store of the config server regardless of the count of services deployed; saves your time and so the money.
Another benefit gained from the config server solution is that you can easily refresh a property by changing it in one place and apply it to the application on runtime without need a restart of all the instances of the services. Yes, that’s exactly perfect.
After explaining why it’s needed, it’s time to look over how the config server architecture works. Here is the simple diagram of the config server architecture.
Let’s dive into the config server architecture diagram:
Config Server is capable of serving all the configuration properties of an application in all environments.
Let’s exemplify a typical use-case:
When a git repository is used as data store, property files are created according to the following rules:
When a config client wants to read the configuration data from the config server, the config client makes a request to the config server with a url named config server url and gets the relevant configuration data as json response.
The config server url is formed of the following structure:
http://config-server-host:port/[application_name]/[profile]/[label]
You can also test your config server by making this request from your browser and analyze the response yourself.
Let’s look over each part of this url:
spring.profiles.active = test, cluster2
This definition means that; if a property is defined both in application-test.properties and application-cluster2.profiles, then the latter one overrides the former one.
A configuration data defined in a properties file can be overridden with a more specific one. The following diagram basically shows this:
The general rules are as follows:
To make a Spring Boot application act as a config server we do the followings:
We need to add the following dependencies to the pom.xml of the Spring Boot config server application for the most basic configuration.
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
To enable the auto-configuration of config server in a Spring Boot application we add the @EnableConfigServer annotation supplied by Spring Cloud.
@EnableConfigServer @SpringBootApplication public class ConfigServerGitApplication { public static void main(String[] args) { SpringApplication.run(ConfigServerGitApplication.class, args); } }
In a file named bootstrap.properties in the config server application, the reference to the data store is set via the use of auto-configuration properties as follows:
###############LOCAL REPOSITORY######################## #spring.cloud.config.server.git.uri = file:///home/erol/dev/app_data/config-repo ###############GITHUB REPOSITORY####################### spring.cloud.config.server.git.uri = https://github.com/erolhira/config-repo-sample.git #spring.cloud.config.server.git.username = my-user-name #spring.cloud.config.server.git.password = my-password
In a Spring application, Spring-managed objects like Spring beans, properties and etc. are held in the Spring application context which is a container for objects having their lifecycles managed by Spring.
In a Spring Cloud application, on the other hand, there is also a bit more inclusive cloud context named bootstrap context. A bootstrap context is the parent context of all the Spring Boot application contexts configured with the same config server and this context is responsible for loading the configuration properties from the config server.
In a Spring Cloud application, initial configuration properties are kept in a file named bootstrap.properties.
In the following diagram, you can see the relation between the two contexts and their property sources.
The default precedence over the property sources is as follows:
Bootstrap Context > Application Context
Config Server > bootstrap.properties > application.properties
A Spring Boot application that’s configured to load its configuration properties from a config server is called a config client. The configuration to be made in the bootstrap.properties for the config client is as follows:
spring.application.name=myconfig-client-app spring.cloud.config.uri=http://localhost:8888 spring.cloud.config.server.git.clone-on-start=true spring.profiles.active=cluster2,instance01
We need to add the following dependencies to the pom.xml of the Spring Boot config client application for the most basic usage.
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
So now, we first run the config server application and type in the browser:
http://localhost:8888/myconfig-client-app/cluster2
As you see, the url does not contain the third parameter which is the label and its default value is master, so here; the configuration data is going to be fetched from the master branch.
And here is the result:
As you see, when you use a property binding in your client application, the value of the property is selected from the highest priority file that can be selected.
According to the example above; if you wire the prop2 in the config client, then it’s value is taken from the myconfig-client-app-cluster2.properties, not from the application.properties.
You can see this by running the sample config client application in my github page and try some alternatives to understand the concept better.
By default, the properties taken from the config server overrides the ones in the local property files.
However, if you want the local ones take precedence over the remote ones, then the following properties have to be defined in a remote property file.
spring.cloud.config.allowOverride=true spring.cloud.config.overrideNone=true spring.cloud.config.overrideSystemProperties=false
In this article, we have looked over the Spring Cloud Config solution architecture and how can it be applied with Git repository.
For further, you can inspect how can it be applied with a jdbc backend instead of Git.
And in the next step, you can work on refresh strategies from basic actuator /refresh endpoint calls to a bit more complicated Spring Cloud Bus integration with streaming solutions like Kafka or Rabbit MQ.
You can see the sample code for this article in my github page, both for the config server and the config client.
https://github.com/erolhira/spring-cloud-config
https://spring.io/projects/spring-cloud-config
https://cloud.spring.io/spring-cloud-config/reference/html/
https://cloud.spring.io/spring-cloud-static/Hoxton.RELEASE/reference/html/spring-cloud-hoxton-configprops.html