Module 35: Centralized Configuration with Spring Cloud Config

Module 35: Centralized Configuration with Spring Cloud Config
In a distributed system, managing configuration across 50+ microservice instances is a logistical nightmare. If you need to change a database password or a feature flag, you don't want to rebuild and redeploy 50 JAR files. You need a Centralized Configuration Server.
Spring Cloud Config provides server 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.
1. The Source of Truth: Config Server
The Config Server is a standalone microservice that centralizes all application properties. It typically uses a Git Repository as the backend, providing:
- Versioning: Every configuration change is a Git commit. You can see historical values and audit changes.
- Auditing: Git's
authorandtimestampidentify exactly who changed which property and when. - Rollback: Instantly revert to a previous configuration state by resetting the Git branch or pointing to a previous commit ID.
- Environment Separation: Use different branches (e.g.,
dev,prod) or logical labels to separate environment-specific configs.
2. Hardware-Mirror: The "Config Thundering Herd"
When a large cluster (e.g., 500 service instances) restarts simultaneously—whether due to a power failure, a major data center migration, or a logic-triggered crash—a phenomenon known as the Thundering Herd occurs.
Physical Hardware Impact:
- NIC Saturation: Every instance calls the Config Server at the same millisecond to fetch its
bootstrap.ymlorapplication.yml. This creates a massive spike in Network Ingress on the Config Server's NIC. If you have 500 instances each requesting 100KB of configuration, that is a sudden 50MB burst. - CPU Spikes (The Decryption Tax): If you use encryption (Symmetric or Asymmetric), the Config Server must decrypt secrets for every request. RSA decryption is CPU-intensive. Hundreds of concurrent decryption requests can peg the Config Server's CPU at 100%, causing request timeouts for the remaining fleet.
- Git I/O Latency: If the server is configured to
clone-on-start(the default), the Config Server must talk to a remote Git provider (GitHub/GitLab). This introduces External Latency and eats up Disk I/O and Memory on the Config Server host.
Hardware-Mirror Rule: For high-density clusters, always enable local filesystem caching on the Config Server (spring.cloud.config.server.git.basedir). Furthermore, scale the Config Server horizontally behind a Load Balancer and ensure the host has a high TCP Backlog setting in the Linux kernel (net.core.somaxconn) to prevent dropped connection packets during the burst.
3. Server Implementation: Building the Brain
To build the server, you need the spring-cloud-config-server dependency.
Maven Dependencies
Main Class
Server Configuration (application.yml)
4. Client Implementation: Import vs. Bootstrap
In Spring Boot 3.x, the way clients fetch config has changed. The legacy bootstrap.yml method is now optional, replaced by the spring.config.import property.
Client Dependencies
Client Configuration (application.yml)
The optional: prefix is vital during local development; it prevents the application from failing if the Config Server isn't reachable.
5. Security: Asymmetric Encryption (RSA)
Storing passwords in plain text in Git is a critical security vulnerability. While Symmetric encryption (AES) is easy, Asymmetric Encryption (RSA) is the enterprise gold standard.
The Hardware Key
- Generate a Keystore: Use the JDK
keytoolto create a.jksfile.bash - Configure the Server:
yaml
- Encrypted Value: Precede your secrets with
{cipher}in the Git YAML.yaml
Hardware-Mirror Insight: Asymmetric decryption requires significantly more CPU Cycles than symmetric. If your cluster is very large, consider decrypting secrets on the Client side to distribute the CPU load, though this requires distributing the private key to every node (increasing security risk).
6. Dynamic Refresh with Spring Cloud Bus
When you change a property in Git, the services don't automatically update. You have three choices:
- Restart: (Slow, Hardware intensive).
- Manual /refresh: POST to every node (Impossible at scale).
- Spring Cloud Bus: (Recommended).
By integrating Module 33: Spring Cloud Bus, you can broadcast a refresh event to the entire fleet via RabbitMQ or Kafka.
This single call triggers a cluster-wide event, causing every node to re-fetch its configuration and re-instantiate @RefreshScope beans instantly.
7. Multi-Backend Strategy: Git + Vault
For high-security environments, you can combine Git (for non-sensitive app settings) with HashiCorp Vault (for secrets).
This hybrid approach allows developers to manage logic-driven config in Git while the Security Team manages tokens and keys in the dedicated Vault hardware.
8. High Availability: Fail-Fast and Retries
If the Config Server is down, your application shouldn't just crash.
Implementation: Retry Logic
This ensures that if the Config Server is struggling with a Thundering Herd, the client will wait and retry rather than immediately dying.
9. Real-World Case Study: The "Phantom" Bootstrap Lag
The Scenario:
A team reported that their microservices were taking 25 seconds to start on their production hardware, compared to 5 seconds in staging.
The Diagnosis:
By analyzing the Network I/O and Disk Watcher on the Config Server, we found that the Config Server was set to clone-on-start: true and had no local cache. Every time a new pod started, the Config Server would perform a deep git clone from a remote GitLab instance across a high-latency VPN.
The Fix:
- Enabled
spring.cloud.config.server.git.basedirto use the local NVMe SSD as a cache. - Set
clone-on-start: falseto allow the server to serve existing cached data while fetching updates asynchronously. - Result: Startup time dropped from 25s to 3s.
10. Summary
Centralized configuration transforms your microservices from rigid, static binaries into a dynamic, "Living" cluster. By understanding the Hardware-Mirror implications of encryption CPU tax and NIC saturation, you can design a Config architecture that handles thousands of nodes and provides sub-second update propagation.
In the next module, Module 36: Service Discovery with Consul, we'll explore how services find the "Brain" and each other in a fluid hardware environment.
Next Steps:
- Set up a Git repository with an
application.yml. - Build a Config Server and point it to your repo.
- Connect a client and verify it receives properties via
curl localhost:8080/actuator/env. - Implement RSA Encryption and verify the Config Server decrypts values on-the-fly.
