Create git repos for configurations. Configurations are either properties or yaml files. Names are like below.
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
Setup properties repos are mainly based on two ways, one repo per application
or one repo per profile
. This demo uses one repo per profile
strategy. Create the strcutre like below in your local repositories.
go to each folder development
, staging
and production
, run following
git init
git add .
git commit -m "add properties file"
The properties files are extremely simple, having only one property example.message
$ cat development/config-repo/config-client-demo.properties
example.message=This is a dev properties
$ cat staging/config-repo/config-client-demo.properties
example.message=This is a staging properties
$ cat production/config-repo/config-client-demo.properties
example.message=This is a production properties
In the example, three local git repositories are created. One is development
repository, one is staging
repository, the last is production
repository. Based on different profile, different properties will be used.
Create project using SPRING INITIALIZR
Simplely add EnableConfigServer
annotation in the main spring boot class.
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
We are using one repo per profile
in the example. Below is the application.yml
. For demo purpose, local repositories are used. For the real config-repos, change to uri
to real gitserver
repositories location.
server:
port: 8888
# spring cloud config repo settings.
spring:
cloud:
config:
server:
git:
uri: https://gitserver/development/config-repo # default repo
repos:
development:
pattern:
- '*/development'
- '*/qa'
uri: C:\\Users\\bzhang\\git-repo\\development\\config-repo
staging:
pattern:
- '*/staging'
uri: C:\\Users\\bzhang\\git-repo\\staging\\config-repo
production:
pattern:
- '*/production'
uri: C:\\Users\\bzhang\\git-repo\\production\\config-repo
local:
pattern:
- '*/local'
uri: C:\\Users\\bzhang\\git-repo\\development\\config-repo
#Disable security of the Management endpoint
management:
security:
enabled: false
From the application.yml
above, you can see there are three repositories for different profiles. development
and qa
are using the same development
repository, the staging
and production
profile has its own repository. Each repository could have its own security controls.
Except one repo per profile
, you can also define your application.yml
like below to demonstrate one repo per application
:
spring:
cloud:
config:
server:
git:
uri: https://gitserver/config-repos/{application}
set spring.cloud.config.server.git.force-pull=true
Spring Cloud Config Server by default makes a clone of the remote git repository and if the local copy gets dirty it cannot update the local copy from remote repository. To solve this problem, there is a force-pull
property that will make Spring Cloud Config Server force pull from remote repository if the local copy is dirty.
spring:
cloud:
config:
server:
git:
uri: https://github.com/production/config-repo
force-pull: true
If you have a multiple repositories configuration you can configure the force-pull property per repository.
Normally, many source code repository providers (like Github) will notify you of changes in a repository through a webhook. You can configure the webhook via the provider’s user interface as a URL and a set of events in which you are interested. For instance Github will POST to the webhook with a JSON body containing a list of commits, and a header "X-Github-Event" equal to "push". If you add a dependency on the spring-cloud-config-monitor
library and activate the Spring Cloud Bus : spring-cloud-starter-bus-amqp
or spring-cloud-starter-bus-kafka
or spring-cloud-starter-bus-redis
. in your Config Server, then a "/monitor" endpoint is enabled.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-monitor</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-redis</artifactId>
<!-- or -amqp (rabbitmq) or -kafka -->
</dependency>
mvn clean install
java -jar target/config-server-0.0.1-SNAPSHOT.jar
Open browser and test those.
http://localhost:8888/config-client-demo/development
http://localhost:8888/config-client-demo/staging
http://localhost:8888/config-client-demo/production
Create project using SPRING INITIALIZR
In client side, you needs to create bootstrap.properties. The bootstrap.properties allows the application connect spring cloud config server first and pulls all properties of this application when it starts. It is defined like this.
$ cat bootstrap.properties
server.port=8001
spring.application.name=config-client-demo
spring.profiles.active=development
spring.cloud.config.uri=http://localhost:8888
management.security.enabled=true
The yaml format is below, they are identical. Either one is fine.
$ cat bootstrap.yml
server:
port: 8001
spring:
application:
name: config-client-demo
spring:
profiles:
active: development
spring:
cloud:
config:
uri: http://localhost:8888
management:
security:
enabled: true
The application name has to match as the {application} in the git repositories.
Compile:
# compile
mvn clean install
# start config-client-demo application with the development profile
java -jar config-client-demo.jar --spring.application.profiles=development
# Test application use another console
curl http://localhost:8001/message
You should get something like this:
This is a dev properties
Try other profiles:staging
and production
:
# start config-client-demo application with staging profiles
java -jar config-client-demo.jar --spring.application.profiles=staging
# start config-client-demo application with production profiles
java -jar config-client-demo.jar --spring.application.profiles=production
curl http://localhost:8001/message
you will get for staging and production
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
@RestController
@RefreshScope
public class MessageController {
@Value("${example.message}")
private String msg;
@RequestMapping("/message")
String getMsg() {
return this.msg;
}
}
When configations change on the config-server, you can trigger /refresh
endpoint manually to reload the config changes.
From above, you need to trigger /refresh
endpoint manually to reload the config changes. This is not practical and viable if you have large number of applications. Spring Cloud Bus
module can be used to implement auto refresh configs. It links multiple applications with a message broker and broadcast configuration changes.
(Continue .. )