Introduction
In the landscape of distributed systems, service discovery and centralized configuration management are critical components. Nacos, Alibaba's open-source platform, provides a robust solution for dynamic service discovery and configuration management. This guide demonstrates how to integrate Nacos with a Spring Boot applicasion to manage microservices effectively.
Understanding Nacos
Nacos (Dynamic Naming and Configuration Service) is designed to simplify cloud-native application development. It supports Kubernetes-native deployement across various cloud environments. The platform offers four primary capabilities:
- Service Discovery and Health Checks: Supports both DNS and RPC-based discovery protocols.
- Dynamic Configuration Service: Manages application configurations centrally via APIs and data models.
- Dynamic DNS Service: Provides weighted routing and easier load balancing.
- Service and Metadata Management: Offers a dashboard to monitor services and manage their metadata.
Project Dependencies
Begin by adding the necessary Spring Cloud Alibaba dependencies to your pom.xml file to enable Nacos discovery and configuration.
<dependencies>
<!-- Nacos Service Discovery -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2021.0.5.0</version>
</dependency>
<!-- Nacos Configuration Management -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2021.0.5.0</version>
</dependency>
</dependencies>
Client Configuration
Configure the connection to the Nacos server in the bootstrap.yml (or application.yml) file. This ensures the application registers with the server and fetches external configurations.
spring:
application:
name: demo-service
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
config:
server-addr: 127.0.0.1:8848
file-extension: yml
Implementing Service Discovery
Enable service registration by annotating the main application class with @EnableDiscoveryClient. Below is an example of the main application class and a controller to verify the service registration.
package com.example.nacos;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class NacosIntegrationApp {
public static void main(String[] args) {
SpringApplication.run(NacosIntegrationApp.class, args);
}
}
Create a REST controller to test the discovery mechanism. The controller will return the name of the registered service.
package com.example.nacos.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ServiceInfoController {
@Value("${spring.application.name}")
private String currentService;
@GetMapping("/service-info")
public String getServiceDetails() {
return "Request served by " + currentService;
}
}
Once the application starts, the Nacos console will display the registered service instance.
Dynamic Configuration Management
To demonstrate centralized configuration, create a configuration file in the Nacos dashboard. For instance, create a file named demo-service.yml with the following content:
app:
config:
greeting: "Welcome to Nacos Config"
In the Spring Boot application, inject this property using the @Value annotation. To allow the bean to update its state when configuration changes, apply the @RefreshScope annotation.
package com.example.nacos.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RefreshScope
public class DynamicConfigController {
@Value("${app.config.greeting}")
private String welcomeMessage;
@GetMapping("/greeting")
public String getGreeting() {
return welcomeMessage;
}
}
Automating Configuration Refresh
To propagate configuration changes across all enstances automatically without manual restarts, integrate Spring Cloud Bus with a message broker like RabbitMQ.
Add the required dependencies to pom.xml:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Configure the message broker connection in the configuration file:
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
management:
endpoints:
web:
exposure:
include: "bus-refresh"
With these settings, you can trigger a configuration refresh broadcast to all connected services by sending a POST request to the actuator endpoint:
curl -X POST http://localhost:8080/actuator/bus-refresh