Centralized Configuration with Apache Zookeeper
1. Overview
In a distributed-oriented architecture such as microservices or SOA, many services (microservices) are put in place, which can make it difficult to configure different services. Hence the establishment of a Centralized Configuration System becomes crucial.
The benefits of a centralized configuration system are :
- Apply the third principal of the Twelve-Factor, that highly recommend storing configs in a centralized system.
- A centralized store gives the possibility to manage configs from one single place.
- No redeploy and no restart are needed when updating the config.
- Keep one single copy of the Common configs, for example database properties (host, username, password).
- When updating the configs, all the nodes of our cluster get notified and refreshed instantly, hence our cluster remains consistent.
- Keep tracking of what is changed and who changed what.
2. Apache Zookeeper
Zookeeper is one of the best centralized services for maintaining configuration, it is widely used by many other solutions like: Apache Hadoop, Kafka, SolrCloud…
2.1. Concept Overview
This is a simplified version of how we are going to setup Zookeeper.
Zookeeper stores data in a tree of ZNodes similar to Linux file system structure, a ZNode may contain another ZNodes or may have a value.
- App1 and App2 are sharing data from / and config znodes.
- However db.host, db.username and db.password are specific to App1.
2.2. Zookeeper Setup
In order to setup the Zookeeper we will use this Docker image netflixoss/exhibitor, it comes with Exhibitor who helps manage and supervise the Zookeeper.
Add the two Znodes to Zookeeper using Exhibitor for Zookeeper UI:
/config/ZookeeperHelloWorld/hello.property1
/config/ZookeeperHelloWorld/hello.property2
Click on Modify and fill the related information about the Znodes:
- ZookeeperHelloWorld is the name of the application (microservice).
- hello.property1 and hello.property2 are two properties, we will use then later on in the application.
3. Implementation
Create a Spring boot project using Spring Initializr, and add Web, Actuator, Zookeeper Configuration dependencies using dependencies box.
Your pom.xml
should look like:
<?xml version="1.0" encoding="UTF-8"?>
<project ... >
<!-- ... -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!-- ... -->
</project>
In a file called bootstrap.properties
in the root of the project classpath add the following properties:
# The name of the application (microservice)
spring.application.name=ZookeeperHelloWorld
# The Zookeeper host and port
spring.cloud.zookeeper.connect-string=192.168.99.100:2181
# Enable auto refresh ou properties values when the config is changed in Zookeeper
spring.cloud.zookeeper.config.watcher.enabled=true
Add a new POJO class called HelloProperties.java
, that will hold the config sent by Zookeeper:
@Component
@ConfigurationProperties("hello")
class HelloProperties {
private String property1;
private String property2;
// getters & setters...
}
Create a RestController
to check out that our properties are getting inflated properly with the right values:
@RestController
public class HelloController {
@Autowired
HelloProperties helloProperties;
@GetMapping("/properties/display")
public HelloProperties displayProperties() {
return helloProperties;
}
}
Find the source code of this example on GitHub.
4. Conclusion
With the current trend of distributed architectures like microservices, it is becoming more and more essential to have a centralized system to manage the configuration.
Zookeeper allows you to manage your configuration very easily thanks to it’s data structure as a tree and some simple command lines.
Software Craftsmanship, Stackextend author and Full Stack developer with 6+ years of experience in Java/Kotlin, Java EE, Angular and Hybris…
I’m Passionate about Microservice architectures, Hexagonal architecture, Event Driven architecture, Event Sourcing and Domain Driven design (DDD)…
Huge fan of Clean Code school, SOLID, GRASP principles, Design Patterns, TDD and BDD.
Thanks for sharing!
how can we decrypt properties here?