Cloud Native 12 min read

How to Use Nacos Config Center in Spring Cloud Microservices

This article explains why scattered application.yml files cause configuration pain in microservices, introduces Nacos Config Center as a solution for unified, real‑time, environment‑isolated configuration management, and walks through quick setup, API usage, code integration, dynamic refresh, best practices, and common pitfalls.

Coder Trainee
Coder Trainee
Coder Trainee
How to Use Nacos Config Center in Spring Cloud Microservices

Why a Config Center Is Needed

In a typical Spring Cloud setup each service maintains its own application.yml, so changing a single property requires editing multiple files, rebuilding, and redeploying. The pain points include configuration dispersion, manual updates, service restarts, mixed development/test/production settings, and lack of version control.

Nacos Config Center Benefits

Unified configuration management

Changes take effect instantly without restarting services

Environment isolation via namespaces and groups

Built‑in versioning and rollback

Quick Start

1. Add Maven Dependency

<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

2. Adjust Bootstrap Configuration

Spring Boot reads application.yml by default, but Nacos configuration must be loaded earlier, so create a bootstrap.yml with higher priority:

# bootstrap.yml (higher priority than application.yml)
spring:
  application:
    name: user-service
  cloud:
    nacos:
      config:
        server-addr: localhost:8848
        file-extension: yaml
        namespace: dev
        group: BLOG_GROUP
        refresh-enabled: true

Place static settings that never change in application.yml (e.g., server port, logging).

3. Create Configuration in Nacos

Via Console : Open http://localhost:8848/nacos → Configuration Management → Configuration List → New Configuration. Fill in Data ID (e.g., user-service-dev.yaml), Group ( BLOG_GROUP), and YAML content.

Via API :

curl -X POST "http://localhost:8848/nacos/v1/cs/configs" \
  -d "dataId=user-service-dev.yaml" \
  -d "group=BLOG_GROUP" \
  -d "content=spring.datasource.url: jdbc:mysql://localhost:3306/blog_user"

4. Use Configuration in Code

Inject values directly:

@RestController
@RequestMapping("/api/config")
@RefreshScope // enables dynamic refresh
public class ConfigController {
    @Value("${spring.datasource.url}")
    private String datasourceUrl;

    @Value("${business.enable-comment:true}")
    private Boolean enableComment;

    @GetMapping("/info")
    public Map<String, Object> getConfig() {
        Map<String, Object> config = new HashMap<>();
        config.put("datasourceUrl", datasourceUrl);
        config.put("enableComment", enableComment);
        return config;
    }
}

Or bind a group of properties:

@Data
@Component
@RefreshScope
@ConfigurationProperties(prefix = "business")
public class BusinessProperties {
    private Boolean enableComment;
    private Boolean enableSearch;
    private Integer maxUploadSize;
    private List<String> whiteList;
    private Map<String, Integer> limits;
}

Configuration Loading Rules

Data ID Naming

${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}

Examples:

Development: user-service-dev.yaml Testing: user-service-test.yaml Production:

user-service-prod.yaml

Multi‑Environment and Shared Configs

# bootstrap.yml (shared configs)
spring:
  cloud:
    nacos:
      config:
        shared-configs:
          - data-id: common-redis.yaml
            group: BLOG_GROUP
            refresh: true
          - data-id: common-datasource.yaml
            group: BLOG_GROUP
            refresh: true
        extension-configs:
          - data-id: user-service-extra.yaml
            group: BLOG_GROUP
            refresh: true

Dynamic Refresh

@RefreshScope Mechanism

@RestController
@RefreshScope
public class DynamicConfigController {
    @Value("${business.some-switch}")
    private String someSwitch;

    @GetMapping("/switch")
    public String getSwitch() { return someSwitch; }
}

Listening to Config Changes

Spring environment events:

@Component
@Slf4j
public class ConfigChangeListener {
    @EventListener
    public void onConfigChange(EnvironmentChangeEvent event) {
        Set<String> keys = event.getKeys();
        log.info("Config changed: {}", keys);
    }
}

Nacos native listener:

@Component
@Slf4j
public class NacosConfigListener {
    @Autowired
    private NacosConfigManager nacosConfigManager;

    @PostConstruct
    public void addListener() throws NacosException {
        String dataId = "user-service-dev.yaml";
        String group = "BLOG_GROUP";
        nacosConfigManager.getConfigService().addListener(dataId, group, new Listener() {
            @Override
            public void receiveConfigInfo(String configInfo) {
                log.info("Config updated:
{}", configInfo);
            }
            @Override
            public Executor getExecutor() { return null; }
        });
    }
}

Blog System Configuration Example

Configuration hierarchy:

Nacos config list:
├── common-redis.yaml          # shared Redis config
├── common-datasource.yaml      # shared DB config
├── user-service-dev.yaml       # user service dev
├── user-service-prod.yaml      # user service prod
├── article-service-dev.yaml    # article service dev
├── article-service-prod.yaml   # article service prod
└── gateway-dev.yaml           # gateway config

Sample common-redis.yaml:

spring:
  redis:
    host: ${REDIS_HOST:localhost}
    port: ${REDIS_PORT:6379}
    password: ${REDIS_PASSWORD:}
    database: 0
    lettuce:
      pool:
        max-active: 20
        max-idle: 10
        min-idle: 5

Sample user-service-dev.yaml (database, JWT, feature flags):

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/blog_user
    username: ${DB_USERNAME:root}
    password: ${DB_PASSWORD:123456}
    hikari:
      maximum-pool-size: 20
  business:
    jwt:
      secret: ${JWT_SECRET:mySecretKey}
      expiration: 3600000
    enable-registration: true
    default-avatar: https://cdn.blog.com/default.png

Configuration Management Best Practices

Priority (high → low): startup parameters, environment variables, Nacos, local application.yml, local bootstrap.yml.

Never hard‑code sensitive data; read from env vars or Kubernetes Secrets.

Use Nacos console to view version history, compare differences, and roll back with one click.

Adopt clear naming conventions (e.g., business.enable-comment) and avoid ambiguous keys like a or size.

Common Pitfalls & Troubleshooting

1. Config Not Taking Effect

Ensure the class is annotated with @RefreshScope.

Verify the Data ID matches the one in Nacos.

Confirm refresh-enabled: true (default is true).

2. Loading Order Confusion

Understand the hierarchy above; higher‑priority sources override lower ones.

3. Local vs Nacos Conflict

Separate mutable configuration (in bootstrap.yml) from static configuration (in application.yml).

4. Bean Not Refreshing After Change

Use @RefreshScope or bind with @ConfigurationProperties combined with @RefreshScope for automatic updates.

Next Episode Preview

Spring Cloud Microservice Practice (Part 6): Sentinel for service fault tolerance and rate limiting.

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.

microservicesconfiguration managementNacosSpring CloudBootstrapDynamic Refresh
Coder Trainee
Written by

Coder Trainee

Experienced in Java and Python, we share and learn together. For submissions or collaborations, DM us.

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.