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.
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: truePlace 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.yamlMulti‑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: trueDynamic 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 configSample 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: 5Sample 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.pngConfiguration 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.
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.
Coder Trainee
Experienced in Java and Python, we share and learn together. For submissions or collaborations, DM us.
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.
