A Guide to Spring Cloud Alibaba Nacos

Nacos is an open-source project for configuration and service discovery in Spring Cloud Alibaba.

Nacos’s service discovery supports almost all mainstream services: Kubernetes Service, gRPC, Dubbo RPC Service, Spring Cloud RESTful Service, and so on.

In this post, I will cover common uses of Spring Cloud Alibaba Nacos. This post is based on Java 21, Spring Boot 3.2.12, Spring Cloud Alibaba 2023.0.3.3 and Nacos 2.4.2.

Next, I will use several simple example applications to show it in action.

Running Nacos

Before using Nacos, we must run a Nacos server.

Running Nacos with Docker

The compose.yaml file:

services:
nacos1:
image: "nacos/nacos-server:v3.0.2"
environment:
- "MODE=standalone"
- "NACOS_AUTH_TOKEN=${NACOS_AUTH_TOKEN}"
- "NACOS_AUTH_IDENTITY_KEY=${NACOS_AUTH_IDENTITY_KEY}"
- "NACOS_AUTH_IDENTITY_VALUE=${NACOS_AUTH_IDENTITY_VALUE}"
ports:
- "8080:8080"
- "8848:8848"
- "9848:9848"
healthcheck:
test: "curl http://localhost:8080"
interval: 5s
timeout: 5s
retries: 5
  • NACOS_AUTH_TOKEN: 用于生成 JWT Token的密钥,使用长度大于32字符的字符串,再经过Base64编码。
  • NACOS_AUTH_IDENTITY_KEY: Nacos Server端之间 Inner API的身份标识的Key,必填。
  • NACOS_AUTH_IDENTITY_VALUE: Nacos Server端之间 Inner API的身份标识的Value,必填。
  • ports:
    • 8080: The Nacos Dashboard’s port.
    • 8848: The Nacos Web API’s port.
    • 9848: The gRPC’s port.

Running Nacos with Docker Compose

docker compose up -d

You need to initialize the password for the admin user nacos when you login to the Nacos Dashboard for the first time.

Nacos as a Configuration Center

1. Create Project and Add Dependencies

Using Gradle

1. Create a Java application with the gradle init command.

$ mkdir spring-cloud-alibaba-nacos-config-demo && cd spring-cloud-alibaba-nacos-config-demo
$ gradle --configuration-cache \
init --use-defaults \
--type java-application \
--package com.taogen.springcloud

2. Gradle configuration

app/build.gradle.kts

plugins {
java
id("org.springframework.boot") version "3.2.12"
// Use the Spring Dependency Management plugin to manage Spring Cloud dependencies.
id("io.spring.dependency-management") version "1.1.7"
}

extra["springCloudAlibabaVersion"] = "2023.0.3.3"

java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}

repositories {
mavenCentral()
}

dependencies {
implementation("com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-config")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-actuator")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

dependencyManagement {
imports {
mavenBom("com.alibaba.cloud:spring-cloud-alibaba-dependencies:${property("springCloudAlibabaVersion")}")
}
}

tasks.withType<Test> {
useJUnitPlatform()
}

Using Maven

1. Create a Java application with mvn command.

$ mvn -B archetype:generate \
-DgroupId=com.taogen.springcloud \
-DartifactId=spring-cloud-alibaba-nacos-config-demo \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DarchetypeVersion=1.5

2. Maven configuration

pom.xml

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.taogen.springcloud</groupId>
<artifactId>spring-cloud-alibaba-nacos-config-demo</artifactId>
<version>1.0-SNAPSHOT</version>

<name>spring-cloud-alibaba-nacos-config-demo</name>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>21</maven.compiler.release>
<java.version>21</java.version>
<spring-boot.version>3.2.12</spring-boot.version>
<spring-cloud-alibaba.version>2023.0.3.3</spring-cloud-alibaba.version>
</properties>

<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

Using Alibaba Initializr

Go to https://start.aliyun.com/

Project Metadata

  • Group: com.taogen.springcloud
  • Artifact: spring-cloud-alibaba-nacos-config-demo

Add dependencies

  • Nacos Configuration
  • Spring Web
  • Spring Boot Actuator

2. Spring Configuration

application.yml

spring:
application:
name: spring-cloud-alibaba-nacos-config-demo
profiles:
active: dev
config:
import: optional:nacos:${spring.application.name}-${spring.profiles.active}.properties?group=DEFAULT_GROUP
nacos:
config:
server-addr: "127.0.0.1:8848"

server:
port: 8090
  • config.import: optional:nacos:{Nacos Data ID}?group=DEFAULT_GROUP.

Nacos Data ID Convention: ${spring.application.name}-${spring.profiles.active}.${file-extension}. For example, spring-cloud-alibaba-nacos-config-demo-dev.properties.

3. Config Client Application

SpringCloudAlibabaNacosConfigDemoApplication.java

package com.taogen.springcloud;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class SpringCloudAlibabaNacosConfigDemoApplication {
@Value("${greeting}")
private String greeting;

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

@GetMapping("/greeting")
public String greeting() {
return greeting;
}
}

4. Add Configurations to Nacos

Open Nacos Dashboard http://localhost:8080

Click the “ConfigManagement” -> “Configurations” on the left navigation bar.

Click the “Create Configuration” button.

Dev configurations

  • Data ID: spring-cloud-alibaba-nacos-config-dev.properties
  • Format: Properties
  • Configuration Content:
    greeting=Hello Dev!
    greeting2=Hi Dev!

Prod configurations

  • Data ID: spring-cloud-alibaba-nacos-config-demo-prod.properties
  • Format: Properties
  • Configuration Content:
    greeting=Hello Prod!
    greeting2=Hi Prod!

4. Start and Verification

Starting Spring Cloud Alibaba Nacos Config Demo

Running the main() method in the SpringCloudAlibabaNacosConfigDemoApplication to start the application.

Verification

Visiting http://localhost:8090/greeting to see the properties value from Spring Cloud Config Server.

You can update spring.profiles.active to see the different properties values.

5. Refresh Configurations

Add the @RefreshScope to your Spring Bean class. When configurations change in Nacos, the value (@Value) injected from Nacos will auto-refresh.

@RestController
@RefreshScope
public class MyController {
@Value("${greeting}")
private String greeting;

@GetMapping("/greeting")
public String greeting() {
return greeting;
}
}

Using @NacosConfig

Using @NacosConfig instead of @Value, the value injected from Nacos will auto-refresh.

@NacosConfig(dataId = "spring-cloud-alibaba-nacos-config-demo-dev.properties", group = "DEFAULT_GROUP", key = "greeting")
private String greeting;

Nacos as Service Discovery

1. Create Project and Add Dependencies

Using Gradle

1. Create a Java application with the gradle init command.

$ mkdir spring-cloud-alibaba-nacos-service-discovery-demo && cd spring-cloud-alibaba-nacos-service-discovery-demo
$ gradle --configuration-cache \
init --use-defaults \
--type java-application \
--package com.taogen.springcloud

2. Gradle configuration

app/build.gradle.kts

plugins {
java
id("org.springframework.boot") version "3.2.12"
// Use the Spring Dependency Management plugin to manage Spring Cloud dependencies.
id("io.spring.dependency-management") version "1.1.7"
}

extra["springCloudAlibabaVersion"] = "2023.0.3.3"
extra["springCloudVersion"] = "2023.0.6"

java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}

repositories {
mavenCentral()
}

dependencies {
implementation("com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-config")
implementation("com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-discovery")
implementation("org.springframework.cloud:spring-cloud-starter-loadbalancer")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-actuator")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

dependencyManagement {
imports {
mavenBom("com.alibaba.cloud:spring-cloud-alibaba-dependencies:${property("springCloudAlibabaVersion")}")
mavenBom("org.springframework.cloud:spring-cloud-dependencies:${property("springCloudVersion")}")
}
}

tasks.withType<Test> {
useJUnitPlatform()
}

Using Maven

1. Create a Java application with mvn command.

$ mvn -B archetype:generate \
-DgroupId=com.taogen.springcloud \
-DartifactId=spring-cloud-alibaba-nacos-service-discovery-demo \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DarchetypeVersion=1.5

2. Maven configuration

pom.xml

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.taogen.springcloud</groupId>
<artifactId>spring-cloud-alibaba-nacos-service-discovery-demo</artifactId>
<version>1.0-SNAPSHOT</version>

<name>spring-cloud-alibaba-nacos-service-discovery-demo</name>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>21</maven.compiler.release>
<java.version>21</java.version>
<spring-boot.version>3.2.12</spring-boot.version>
<spring-cloud-alibaba.version>2023.0.3.3</spring-cloud-alibaba.version>
<spring-cloud.version>2023.0.6</spring-cloud.version>
</properties>

<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

Using Alibaba Initializr

Go to https://start.aliyun.com/

Project Metadata

  • Group: com.taogen.springcloud
  • Artifact: spring-cloud-alibaba-nacos-config-demo

Add dependencies

  • Nacos Configuration
  • Nacos Service Discovery
  • Cloud LoadBalancer
  • Spring Web
  • Spring Boot Actuator

2. Spring Configuration

The spring configuration mainly contains Nacos configurations.

application.yml

spring:
application:
name: nacos-service-discovery-1
profiles:
active: dev
config:
import: optional:nacos:${spring.application.name}-${spring.profiles.active}.properties?group=DEFAULT_GROUP
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
discovery:
server-addr: 127.0.0.1:8848

server:
# configure the service to use a random port number
port: 0

3. Nacos Service Discovery Application

SpringCloudAlibabaNacosServiceDiscoveryApplication.java

package com.taogen.springcloud;  

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

4. Start and Verification

Starting the Application

Running the main() method in the SpringCloudAlibabaNacosServiceDiscoveryApplication to start the application.

Verification

Visiting the Nacos dashboard page http://localhost:8080/, go to the “ServiceManagement” - “Service List” page and see whether the service is registered in the Nacos.

5. Call Nacos Services with Spring Cloud LoadBalancer

Spring RestTemplate as a LoadBalancer Client

@Configuration
public class MyConfiguration {
@Bean
@LoadBalanced
public RestTemplate loadBalancedRestTemplate() {
return new RestTemplate();
}
}
@Autowired
private RestTemplate loadBalancedRestTemplate;

public String doSomething() {
String serviceUrl = "http://{nacos-service-id}/{endpoint}";
String response = loadBalancedRestTemplate.getForObject(serviceUrl, String.class);
}

References

[1] Spring Cloud Alibaba 注册配置中心

[2] Nacos 文档

[3] Spring Cloud Alibaba 微服务原理与实战 by 谭锋