Why We Dropped Nacos for Apollo: A Hands‑On Guide to Configuration Management
This article explains why the team replaced Nacos with Ctrip's open‑source Apollo configuration center, outlines Apollo's core concepts, features, and architecture, and provides step‑by‑step instructions for creating projects, testing dynamic updates, exploring environments, clusters, namespaces, and deploying a SpringBoot application on Kubernetes.
1. Basic Concepts
Apollo is an open‑source configuration management center developed by Ctrip, designed to centralize configuration for multiple environments and clusters, support real‑time updates, gray releases, and fine‑grained permission and audit mechanisms.
1.1 Background
As applications grow more complex, traditional file‑based or database configurations cannot meet the demand for real‑time changes, gray releases, and multi‑environment management, prompting the creation of Apollo.
1.2 Introduction
Apollo provides centralized management of key‑value configurations across environments and clusters, with real‑time push capabilities.
1.3 Features
Simple deployment
Gray release support
Version management
Open API platform
Client configuration monitoring
Native Java and .NET clients
Hot (real‑time) updates
Permission management, release audit, operation audit
Unified management of different environments and clusters
1.4 Basic Model
The basic workflow consists of:
User modifies and publishes a configuration in the config center.
The config center notifies Apollo clients of the update.
Clients pull the latest configuration, update local cache, and notify the application.
1.5 Four Dimensions of Apollo
Apollo manages configurations across four dimensions:
application (app.id)
environment (FAT, UAT, DEV, PRO)
cluster (e.g., data‑center based groups)
namespace (logical grouping similar to separate config files)
1.6 Local Cache
Clients cache configuration files locally (e.g., /opt/data/{appId}/config-cache on Linux or C:\opt\data\{appId}\config-cache on Windows) to ensure availability when the server is unreachable.
{appId}+{cluster}+{namespace}.properties1.7 Client Design
Clients maintain a long‑polling HTTP connection to receive push notifications. If no change occurs within 60 seconds, the server returns 304. Clients also periodically pull configurations as a fallback, typically every 5 minutes (configurable via apollo.refreshInterval).
1.8 Overall Design
Config Service handles read/push operations, Admin Service handles modifications, both are stateless and registered to Eureka. A Meta Server abstracts service discovery, and clients resolve service addresses via the Meta Server.
2. Creating an Apollo Project and Configuration
2.1 Login to Apollo
Access the Apollo portal (deployed via NodePort) with username apollo and password admin.
2.2 Modify Department Data
Since Apollo does not provide UI for department management, modify the ApolloPortalDB tables directly to add custom departments.
2.3 Create a Project
After updating the department data, create a new project with Application ID apollo-test and Application Name apollo-demo.
2.4 Create a Configuration Parameter
Add a key test with value 123456 and a remark, then save and publish.
3. Building an Apollo Client Demo
3.1 Add Maven Dependency
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client</artifactId>
<version>1.4.0</version>
</dependency>3.2 Add Configuration to application.yml
apollo.meta: Apollo server address apollo.cluster: Target cluster apollo.bootstrap.enabled: Enable Apollo apollo.bootstrap.namespaces: Namespaces to load (default application) apollo.cacheDir: Local cache directory apollo.autoUpdateInjectedSpringProperties: Whether Spring placeholders update at runtime apollo.bootstrap.eagerLoad.enabled: Load Apollo before logging initialization
server:
port: 8080
spring:
application:
name: apollo-demo
app:
id: apollo-test
apollo:
cacheDir: /opt/data/
cluster: default
meta: http://192.168.2.11:30002
autoUpdateInjectedSpringProperties: true
bootstrap:
enabled: true
namespaces: application
eagerLoad:
enabled: false3.3 Create Test Controller
@RestController
public class TestController {
@Value("${test:默认值}")
private String test;
@GetMapping("/test")
public String test() {
return "test的值为:" + test;
}
}3.4 Create Application Entry
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}3.5 JVM Parameters
When running in Kubernetes, set:
-Dapollo.configService=http://192.168.2.11:30002 -Denv=DEV4. Running Tests
4.1 Verify Initial Value
Access http://localhost:8080/test – the response shows test的值为:123456, confirming the value comes from Apollo.
4.2 Update Value in Apollo
Change test to 666666 in the portal, publish, and refresh the endpoint – the response updates accordingly.
4.3 Rollback
After rolling back the configuration, the endpoint returns the previous value 123456.
4.4 Simulate Config Center Failure
Modify the JVM argument to point to an invalid address. The application still returns 123456 because the client falls back to the local cache.
Delete the cache files and restart; the endpoint now returns the default value defined in the @Value placeholder.
4.5 Delete Parameter
Removing the test key from Apollo causes the endpoint to fall back to the default value.
5. Exploring Environments, Clusters, and Namespaces
5.1 Different Environments
Configure a PRO environment in Apollo, add the same test key with a different value, and switch the client by setting env=PRO and updating apollo.meta. The endpoint then reflects the production value.
5.2 Different Clusters
Create clusters beijing and shanghai, each with distinct test values. By setting apollo.cluster to the desired cluster, the client retrieves the corresponding value.
5.3 Different Namespaces
Create private namespaces dev-1 and dev-2, each holding a different test value. Set apollo.bootstrap.namespaces to the target namespace to fetch its configuration.
6. Deploying a SpringBoot Application on Kubernetes with Apollo
6.1 Build Docker Image
Compile the project with Maven, create a Dockerfile that defines JAVA_OPTS (e.g., timezone) and APP_OPTS (Apollo parameters), and build the image:
$ mvn clean install
$ docker build -t mydlqclub/springboot-apollo:0.0.1 .6.2 Kubernetes Deployment
Create a Service of type NodePort and a Deployment that sets the environment variables:
JAVA_OPTS="-Denv=DEV" APP_OPTS="--app.id=apollo-demo --apollo.bootstrap.enabled=true ... --apollo.meta=http://service-apollo-config-server-dev.mydlqcloud:8080"Apply the manifest:
$ kubectl apply -f springboot-apollo.yaml -n mydlqcloud6.3 Test Deployed Service
Access the NodePort (e.g., http://192.168.2.11:31081/test) and verify the value 123456 is returned, confirming successful integration with Apollo in a Kubernetes environment.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Architect Handbook
Focused on Java interview questions and practical article sharing, covering algorithms, databases, Spring Boot, microservices, high concurrency, JVM, Docker containers, and ELK-related knowledge. Looking forward to progressing together with you.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
