Why We Dropped Nacos for Apollo: A Hands‑On Guide to Apollo Configuration Center

This article walks through the reasons for abandoning Nacos in favor of Apollo and provides a step‑by‑step tutorial that covers Apollo’s core concepts, architecture, client integration with Spring Boot, dynamic updates, environment/cluster/namespace handling, and deployment on Kubernetes.

Architect's Guide
Architect's Guide
Architect's Guide
Why We Dropped Nacos for Apollo: A Hands‑On Guide to Apollo Configuration Center

Overview

Apollo is an open‑source distributed configuration center from Ctrip that provides feature parity with Nacos and is designed for complex micro‑service environments.

Core Concepts

When applications grow, static files or databases cannot meet the need for real‑time configuration changes, feature flags, and environment‑specific settings. A centralized configuration center solves these problems.

Key Features

Simple deployment

Gray (canary) release

Version management

Open API

Client configuration monitoring

Native Java and .NET clients

Hot‑update of configurations

Permission, audit and release workflow

Core Model

User modifies a configuration in Apollo and publishes it.

The Config Service notifies connected Apollo clients.

Clients pull the latest configuration, update the in‑memory cache and notify the application.

Four Management Dimensions

Application – identified by app.id Environment – DEV, FAT, UAT, PRO

Cluster – a logical group of instances (e.g., Beijing, Shanghai)

Namespace – logical grouping of keys (public, private, inherited)

Local Cache

Clients cache configuration files under /opt/data/{appId}/config-cache on Linux/macOS or C:\opt\data\{appId}\config-cache on Windows. The cache file name follows the pattern {appId}+{cluster}+{namespace}.properties.

Client Design

Each client maintains a long‑polling HTTP connection (default 60 s) with the Config Service. If a change occurs, the server returns the affected namespace; otherwise it returns HTTP 304. A fallback pull runs every apollo.refreshInterval minutes (default 5 min) and reports the local version to the server.

Overall Architecture

Config Service – provides configuration read and push APIs; stateless and accessed directly by applications.

Admin Service – handles configuration creation, modification and publishing; used by the Apollo Portal.

Meta Server – registers Config Service and Admin Service with Eureka and exposes a unified meta endpoint.

Portal – UI for managing projects, environments, clusters and namespaces; discovers services via the Meta Server.

Availability Scenarios

One Config Service down – no impact; clients reconnect to other instances.

All Config Services down – clients cannot fetch new configs; they continue to use the local cache.

One Admin Service down – no impact; Portal reconnects to other instances.

All Admin Services down – Portal cannot publish, but clients keep working.

One Portal down – no impact; load balancer redirects to a healthy instance.

All Portals down – clients unaffected; Portal unavailable.

One data‑center down – no impact; multi‑DC deployment with automatic failover.

Step‑by‑Step Tutorial

1. Create a Project in Apollo Portal

Log in (default user: apollo, password: admin), create a project with app.id = apollo-test and app.name = apollo-demo.

2. Add a Configuration

Create a key test with value 123456, add a remark and publish.

3. Build a Spring Boot Client

Maven dependency (Apollo client 1.4.0):

<dependency>
  <groupId>com.ctrip.framework.apollo</groupId>
  <artifactId>apollo-client</artifactId>
  <version>1.4.0</version>
</dependency>

application.yml (essential properties):

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: false

TestController :

@RestController
public class TestController {
    @Value("${test:默认值}")
    private String test;

    @GetMapping("/test")
    public String test() {
        return "test的值为:" + test;
    }
}

Application entry point :

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Run the jar with JVM arguments, e.g.:

-Dapollo.configService=http://192.168.2.11:30002 -Denv=DEV

4. Verify

Access http://localhost:8080/test. The response should be test的值为:123456, confirming that the value comes from Apollo.

5. Dynamic Update

Change the test value in the Portal to 666666 and publish. The endpoint immediately returns the new value.

6. Rollback

Rolling back restores the previous value ( 123456) without redeploying the client.

7. Deletion

Deleting the key makes the controller fall back to the default value defined in @Value ( 默认值).

8. Cache Behaviour

If the Config Service is unreachable, the client reads the locally cached file and returns the last known value. Deleting the cache file forces the default value.

Environment / Cluster / Namespace Switch

Environment Switch

Set apollo.meta to the PRO address and start the JVM with -Denv=PRO. The same key now returns the value defined in the PRO environment.

Cluster Switch

Define apollo.cluster: beijing (or shanghai) in application.yml. After publishing different values for each cluster, the endpoint returns the cluster‑specific value.

Namespace Switch

Create private namespaces (e.g., dev-1, dev-2) and select the desired namespace via bootstrap.namespaces. The endpoint returns the value belonging to the selected namespace.

Kubernetes Deployment

Docker Image

FROM openjdk:8u222-jre-slim
VOLUME /tmp
ADD target/*.jar app.jar
ENV JAVA_OPTS="-XX:MaxRAMPercentage=80.0 -Duser.timezone=Asia/Shanghai"
ENV APP_OPTS=""
ENTRYPOINT ["sh","-c","java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar $APP_OPTS"]

Build the image:

docker build -t mydlqclub/springboot-apollo:0.0.1 .

Kubernetes Manifest (springboot‑apollo.yaml)

apiVersion: v1
kind: Service
metadata:
  name: springboot-apollo
spec:
  type: NodePort
  ports:
  - name: server
    nodePort: 31080
    port: 8080
    targetPort: 8080
  - name: management
    nodePort: 31081
    port: 8081
    targetPort: 8081
  selector:
    app: springboot-apollo
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: springboot-apollo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: springboot-apollo
  template:
    metadata:
      labels:
        app: springboot-apollo
    spec:
      containers:
      - name: springboot-apollo
        image: mydlqclub/springboot-apollo:0.0.1
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
          name: server
        env:
        - name: JAVA_OPTS
          value: "-Denv=DEV"
        - name: APP_OPTS
          value: " \
          --app.id=apollo-demo \
          --apollo.bootstrap.enabled=true \
          --apollo.bootstrap.eagerLoad.enabled=false \
          --apollo.cacheDir=/opt/data/ \
          --apollo.cluster=default \
          --apollo.bootstrap.namespaces=application \
          --apollo.autoUpdateInjectedSpringProperties=true \
          --apollo.meta=http://service-apollo-config-server-dev.mydlqcloud:8080"
        resources:
          limits:
            memory: 1000Mi
            cpu: 1000m
          requests:
            memory: 500Mi
            cpu: 500m

Deploy to the desired namespace (e.g., mydlqcloud) with:

kubectl apply -f springboot-apollo.yaml -n mydlqcloud

Test the Deployed Service

Assuming the cluster node IP is 192.168.2.11 and the NodePort is 31080, access http://192.168.2.11:31080/test. The response should be the value stored in Apollo (e.g., 123456).

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

DockerKubernetesConfiguration ManagementSpring BootApollo
Architect's Guide
Written by

Architect's Guide

Dedicated to sharing programmer-architect skills—Java backend, system, microservice, and distributed architectures—to help you become a senior architect.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.