当前位置: 首页 > news >正文

从 0 到 1 精通 Nacos:服务发现与配置中心的实战指南

引言:为什么 Nacos 是微服务架构的必备神器?

在微服务架构盛行的今天,服务治理成为了系统设计中不可或缺的一环。想象一下,当你的系统从单体应用拆分为数十甚至上百个微服务时,如何高效地管理这些服务的注册与发现?如何在不重启服务的情况下动态调整配置?如何实现服务的负载均衡与故障转移?

Nacos(Dynamic Naming and Configuration Service)应运而生,它是阿里巴巴开源的一款集服务发现、配置管理于一体的中间件。自 2018 年开源以来,Nacos 凭借其强大的功能、优异的性能和易用性,迅速成为微服务生态中的佼佼者,被广泛应用于各类企业级系统中。

本文将带你全面深入地了解 Nacos,从核心概念到底层原理,从环境搭建到实战应用,让你真正掌握这一微服务利器。无论你是刚接触微服务的新手,还是寻求进阶的资深开发者,都能从本文中获益。

一、Nacos 核心概念与架构解析

1.1 什么是 Nacos?

Nacos 是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。它提供了一组简单易用的特性集,帮助开发者快速实现动态服务发现、服务配置、服务元数据及流量管理。

Nacos 的名字来源于以下几个词的组合:

  • Naming:服务命名与发现
  • Configuration:配置管理
  • Service:服务管理

简单来说,Nacos 就是微服务的 "通讯录"(服务发现)和 "控制面板"(配置管理)。

1.2 Nacos 的核心功能

Nacos 主要提供两大核心功能:

  1. 服务发现与服务健康检查

    • 支持基于 DNS 和 RPC 的服务发现
    • 实时健康检查,防止向不健康的服务实例发送请求
    • 支持多种健康检查方式:TCP、HTTP、MySQL 等
  2. 动态配置服务

    • 集中式配置管理,支持动态更新
    • 配置版本控制与回滚
    • 配置变更监听与推送

除此之外,Nacos 还提供了服务元数据管理、流量管理等高级特性,为微服务架构提供了全方位的支持。

1.3 Nacos 架构设计

Nacos 的架构设计充分考虑了高可用性、 scalability 和灵活性,其核心架构如图所示:

Nacos 架构主要包含以下几个部分:

  1. 客户端(Client):集成在应用中的 Nacos 客户端,负责与服务器通信
  2. Nacos 服务器集群(Nacos Server Cluster):提供服务发现和配置管理的核心服务
  3. 存储层
    • 嵌入式存储:用于单机模式,简化部署
    • 外部存储:主要是 MySQL,用于集群模式,保证数据一致性
  4. 核心服务
    • 配置服务(Config Service):处理配置相关的请求
    • 命名服务(Naming Service):处理服务发现相关的请求

1.4 Nacos 的两种运行模式

Nacos 支持两种运行模式,以适应不同的场景需求:

  1. 单机模式

    • 适用于开发、测试环境
    • 使用嵌入式数据库(Derby)存储数据
    • 部署简单,无需额外配置数据库
  2. 集群模式

    • 适用于生产环境
    • 必须使用外部数据库(MySQL)存储数据
    • 多节点部署,提供高可用性和负载均衡

二、Nacos 环境搭建与配置

2.1 准备工作

在开始搭建 Nacos 环境之前,我们需要准备以下环境:

  • JDK 17+(推荐使用 JDK 17)
  • MySQL 8.0+(集群模式需要)
  • Maven 3.6+(源码编译需要)
  • Git(源码下载需要)

2.2 下载与安装 Nacos

2.2.1 二进制包安装(推荐)

Nacos 官方提供了预编译的二进制包,我们可以直接下载使用:

# 下载最新稳定版本(当前最新稳定版为2.3.2)
wget https://github.com/alibaba/nacos/releases/download/2.3.2/nacos-server-2.3.2.tar.gz# 解压
tar -zxvf nacos-server-2.3.2.tar.gz# 进入nacos目录
cd nacos/bin
2.2.2 源码编译安装

如果需要自定义 Nacos 或体验最新功能,可以从源码编译:

# 克隆源码仓库
git clone https://github.com/alibaba/nacos.git# 进入源码目录
cd nacos# 切换到稳定版本分支
git checkout 2.3.2# 编译打包
mvn -Prelease-nacos -Dmaven.test.skip=true clean install -U# 进入编译后的目录
cd distribution/target/nacos-server-2.3.2/nacos/bin

2.3 单机模式启动

单机模式下,Nacos 使用嵌入式数据库,无需额外配置:

# Linux/Unix/Mac系统
sh startup.sh -m standalone# Windows系统
cmd startup.cmd -m standalone

启动成功后,访问 http://localhost:8848/nacos 即可打开 Nacos 控制台,默认用户名和密码都是 nacos。

2.4 集群模式配置与启动

集群模式需要使用 MySQL 数据库,提供更高的可用性和扩展性。

2.4.1 数据库配置
  1. 首先创建 MySQL 数据库(推荐使用 MySQL 8.0):
CREATE DATABASE nacos_config CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  1. 导入初始化 SQL 脚本,脚本位于 Nacos 安装目录的 conf/nacos-mysql.sql:
# 使用mysql命令导入
mysql -u root -p nacos_config < ../conf/nacos-mysql.sql
  1. 修改 Nacos 配置文件 conf/application.properties,添加数据库配置:
# 数据源平台 可选值:mysql/oracle/postgresql
spring.datasource.platform=mysql# 数据库数量
db.num=1# 数据库连接信息
db.url.0=jdbc:mysql://localhost:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user.0=root
db.password.0=your_password# 连接池配置
db.pool.config.connectionTimeout=30000
db.pool.config.validationTimeout=10000
db.pool.config.maximumPoolSize=20
db.pool.config.minimumIdle=5
2.4.2 集群配置
  1. 在 conf 目录下创建 cluster.conf 文件,添加所有节点的 IP 和端口:
192.168.1.101:8848
192.168.1.102:8848
192.168.1.103:8848
  1. 分别在每个节点上启动 Nacos:
# Linux/Unix/Mac系统
sh startup.sh# Windows系统
cmd startup.cmd
2.4.3 配置负载均衡(可选)

为了提高可用性,可以在 Nacos 集群前配置负载均衡器(如 Nginx):

upstream nacos_cluster {server 192.168.1.101:8848;server 192.168.1.102:8848;server 192.168.1.103:8848;
}server {listen 80;server_name nacos.example.com;location / {proxy_pass http://nacos_cluster;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;}
}

2.5 Nacos 控制台介绍

Nacos 提供了直观易用的 Web 控制台,主要包含以下功能模块:

  1. 服务管理:查看和管理注册的服务及其实例
  2. 配置管理:管理配置集和配置项
  3. 命名空间:实现配置和服务的隔离
  4. 集群管理:查看集群节点状态
  5. 权限控制:管理用户、角色和权限

登录控制台后,可以直观地看到 Nacos 的各项功能,通过图形化界面进行操作。

三、Nacos 配置中心实战

配置中心是 Nacos 的核心功能之一,它解决了分布式系统中配置管理的痛点。本节将详细介绍如何使用 Nacos 作为配置中心。

3.1 配置中心核心概念

在使用 Nacos 配置中心之前,我们需要了解几个核心概念:

  1. 配置项(Config Item):一个具体的配置参数及其值,如server.port=8080
  2. 配置集(Config Set):一组相关或不相关的配置项的集合,通常对应一个配置文件
  3. 配置集 ID(Data ID):配置集的唯一标识,通常采用类文件名的命名规则,如application.properties
  4. 命名空间(Namespace):用于隔离不同环境的配置,如开发、测试、生产环境
  5. 分组(Group):用于对配置集进行分组管理,默认分组为DEFAULT_GROUP

3.2 在 Nacos 控制台创建配置

  1. 登录 Nacos 控制台,进入 "配置管理" -> "配置列表"
  2. 点击 "新建配置" 按钮,填写配置信息:
    • Data ID:example-service.properties
    • Group:DEFAULT_GROUP
    • 配置格式:Properties
    • 配置内容:
      # 服务端口
      server.port=8081
      # 应用名称
      spring.application.name=example-service
      # 测试配置
      app.title=Nacos Example
      app.description=This is a Nacos example service
      app.enableFeature=true
      app.maxConnections=100
      
  3. 点击 "发布" 按钮保存配置

3.3 Spring Cloud 集成 Nacos 配置中心

下面我们将创建一个 Spring Boot 应用,集成 Nacos 配置中心,实现配置的动态获取和更新。

3.3.1 创建 Maven 项目,添加依赖
<?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><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.0</version><relativePath/></parent><groupId>com.example</groupId><artifactId>nacos-config-example</artifactId><version>1.0.0</version><name>nacos-config-example</name><description>Nacos Config Example</description><properties><java.version>17</java.version><spring-cloud-alibaba.version>2023.0.0.0</spring-cloud-alibaba.version></properties><dependencies><!-- Spring Boot Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Spring Cloud Alibaba Nacos Config --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><!-- Lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.30</version><optional>true</optional></dependency><!-- Spring Boot Starter Test --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- Swagger3 --><dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-starter-webmvc-ui</artifactId><version>2.3.0</version></dependency></dependencies><dependencyManagement><dependencies><!-- Spring Cloud Alibaba --><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></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build>
</project>
3.3.2 创建配置文件

创建bootstrap.properties文件(注意:必须使用 bootstrap 而不是 application,因为配置中心的配置需要在应用启动早期加载):

# Nacos配置中心地址
spring.cloud.nacos.config.server-addr=localhost:8848# 配置文件的Data ID
spring.cloud.nacos.config.name=example-service# 配置文件的Group
spring.cloud.nacos.config.group=DEFAULT_GROUP# 配置文件的格式
spring.cloud.nacos.config.file-extension=properties# 命名空间,默认为public
# spring.cloud.nacos.config.namespace=public
3.3.3 创建配置实体类
package com.example.nacosconfigexample.config;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;/*** 应用配置类,用于映射Nacos中的配置* * @author ken*/
@Data
@Component
@ConfigurationProperties(prefix = "app")
@RefreshScope // 开启配置自动刷新
public class AppConfig {/*** 应用标题*/private String title;/*** 应用描述*/private String description;/*** 是否启用新功能*/private boolean enableFeature;/*** 最大连接数*/private int maxConnections;
}
3.3.4 创建控制器,使用配置
package com.example.nacosconfigexample.controller;import com.example.nacosconfigexample.config.AppConfig;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** 配置演示控制器* * @author ken*/
@RestController
@RequestMapping("/config")
@Slf4j
@RefreshScope // 开启配置自动刷新
@Tag(name = "配置演示接口", description = "用于演示Nacos配置中心功能的接口")
public class ConfigController {/*** 注入配置实体类*/@Autowiredprivate AppConfig appConfig;/*** 使用@Value注解获取配置*/@Value("${app.title:默认标题}")private String appTitle;/*** 获取应用配置* * @return 应用配置信息*/@GetMapping("/app")@Operation(summary = "获取应用配置", description = "获取从Nacos配置中心加载的应用配置信息")public AppConfig getAppConfig() {log.info("获取应用配置: {}", appConfig);return appConfig;}/*** 获取应用标题* * @return 应用标题*/@GetMapping("/title")@Operation(summary = "获取应用标题", description = "通过@Value注解获取应用标题")public String getAppTitle() {log.info("获取应用标题: {}", appTitle);return appTitle;}
}
3.3.5 创建启动类
package com.example.nacosconfigexample;import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.info.Info;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** Nacos配置中心示例应用启动类* * @author ken*/
@SpringBootApplication
@OpenAPIDefinition(info = @Info(title = "Nacos配置中心示例API",version = "1.0.0",description = "用于演示Nacos配置中心功能的API文档")
)
public class NacosConfigExampleApplication {public static void main(String[] args) {SpringApplication.run(NacosConfigExampleApplication.class, args);}
}
3.3.6 运行与测试
  1. 启动 Nacos 服务器(单机模式)
  2. 启动 Spring Boot 应用
  3. 访问 Swagger UI:http://localhost:8081/swagger-ui/index.html
  4. 调用/config/app接口,查看返回的配置信息
  5. 在 Nacos 控制台修改配置,例如将app.title改为 "Updated Nacos Example"
  6. 再次调用/config/app接口,观察配置是否已自动更新

3.4 配置动态刷新原理

Nacos 配置中心的动态刷新功能是如何实现的呢?让我们来深入了解其底层原理:

具体流程如下:

  1. 当 Nacos 服务器上的配置发生变更时,会主动推送变更通知给客户端
  2. Nacos 客户端接收到变更通知后,会从服务器拉取最新的配置
  3. 客户端触发 Spring 的RefreshEvent事件
  4. @RefreshScope注解对应的处理器捕获到该事件
  5. 处理器会销毁当前作用域内的 Bean,并在下一次访问时重新创建
  6. 新创建的 Bean 会加载最新的配置信息,从而实现配置的动态更新

3.5 多环境配置管理

在实际开发中,我们通常需要区分开发、测试、生产等不同环境的配置。Nacos 提供了两种方式实现多环境配置管理:

3.5.1 使用命名空间(Namespace)隔离环境
  1. 在 Nacos 控制台创建命名空间:

    • 开发环境:dev
    • 测试环境:test
    • 生产环境:prod
  2. 在对应命名空间下创建配置

  3. 在应用中指定命名空间:

# 指定命名空间ID(注意是ID而不是名称)
spring.cloud.nacos.config.namespace=dev-namespace-id
3.5.2 使用配置分组(Group)区分环境
  1. 在 Nacos 控制台创建不同分组的配置:

    • 开发环境:DEV_GROUP
    • 测试环境:TEST_GROUP
    • 生产环境:PROD_GROUP
  2. 在应用中指定分组:

# 指定配置分组
spring.cloud.nacos.config.group=DEV_GROUP
3.5.3 使用配置文件后缀区分环境
  1. 创建不同环境的配置文件:

    • 开发环境:example-service-dev.properties
    • 测试环境:example-service-test.properties
    • 生产环境:example-service-prod.properties
  2. 在应用中通过spring.profiles.active指定环境:

# 激活的环境
spring.profiles.active=dev# 配置文件的Data ID,会自动拼接为example-service-dev.properties
spring.cloud.nacos.config.name=example-service
spring.cloud.nacos.config.file-extension=properties

3.6 配置共享与优先级

在微服务架构中,多个服务可能会共享一些配置,同时每个服务又有自己的个性化配置。Nacos 提供了灵活的配置共享机制。

3.6.1 共享配置

可以通过shared-configs配置多个共享的配置:

# 共享配置
spring.cloud.nacos.config.shared-configs[0].data-id=common.properties
spring.cloud.nacos.config.shared-configs[0].group=COMMON_GROUP
spring.cloud.nacos.config.shared-configs[0].refresh=truespring.cloud.nacos.config.shared-configs[1].data-id=db.properties
spring.cloud.nacos.config.shared-configs[1].group=COMMON_GROUP
spring.cloud.nacos.config.shared-configs[1].refresh=true
3.6.2 扩展配置

还可以通过extension-configs配置扩展配置,与共享配置类似,但优先级更高:

# 扩展配置
spring.cloud.nacos.config.extension-configs[0].data-id=redis.properties
spring.cloud.nacos.config.extension-configs[0].group=EXT_GROUP
spring.cloud.nacos.config.extension-configs[0].refresh=true
3.6.3 配置优先级

Nacos 配置的优先级从高到低如下:

  1. 应用名 + 环境名.properties(如 example-service-dev.properties)
  2. 扩展配置(extension-configs)
  3. 共享配置(shared-configs)
  4. 应用名.properties(如 example-service.properties)

四、Nacos 服务发现实战

服务发现是微服务架构中的核心组件,负责管理服务的注册与发现,实现服务之间的通信。Nacos 提供了强大的服务发现功能,本节将详细介绍其使用方法。

4.1 服务发现核心概念

在使用 Nacos 服务发现之前,我们需要了解几个核心概念:

  1. 服务(Service):一个提供特定功能的应用实例集合,如用户服务、订单服务等
  2. 服务实例(Instance):服务的具体运行实例,一个服务可以有多个实例
  3. 元数据(Metadata):服务或实例的附加信息,如版本号、权重、环境等
  4. 健康检查(Health Check):Nacos 定期检查服务实例是否可用的机制

4.2 Spring Cloud 集成 Nacos 服务发现

下面我们将创建两个微服务:服务提供者和服务消费者,演示如何使用 Nacos 实现服务发现和调用。

4.2.1 服务提供者

1. 创建 Maven 项目,添加依赖

<?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><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.0</version><relativePath/></parent><groupId>com.example</groupId><artifactId>nacos-provider-example</artifactId><version>1.0.0</version><name>nacos-provider-example</name><description>Nacos Service Provider Example</description><properties><java.version>17</java.version><spring-cloud-alibaba.version>2023.0.0.0</spring-cloud-alibaba.version></properties><dependencies><!-- Spring Boot Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Spring Cloud Alibaba Nacos Discovery --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!-- Lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.30</version><optional>true</optional></dependency><!-- Spring Boot Starter Test --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- Swagger3 --><dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-starter-webmvc-ui</artifactId><version>2.3.0</version></dependency></dependencies><dependencyManagement><dependencies><!-- Spring Cloud Alibaba --><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></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build>
</project>

2. 创建配置文件 application.properties

# 服务端口
server.port=8081# 服务名称(服务发现的关键标识)
spring.application.name=user-service# Nacos服务发现地址
spring.cloud.nacos.discovery.server-addr=localhost:8848# 服务元数据(可选)
spring.cloud.nacos.discovery.metadata.version=1.0
spring.cloud.nacos.discovery.metadata.weight=10
spring.cloud.nacos.discovery.metadata.env=dev# 开启服务注册与发现
spring.cloud.nacos.discovery.enabled=true

3. 创建实体类 User

package com.example.nacosproviderexample.entity;import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;/*** 用户实体类* * @author ken*/
@Data
@Schema(description = "用户实体")
public class User {/*** 用户ID*/@Schema(description = "用户ID")private Long id;/*** 用户名*/@Schema(description = "用户名")private String username;/*** 用户年龄*/@Schema(description = "用户年龄")private Integer age;/*** 用户邮箱*/@Schema(description = "用户邮箱")private String email;
}

4. 创建控制器 UserController

package com.example.nacosproviderexample.controller;import com.example.nacosproviderexample.entity.User;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** 用户服务控制器* * @author ken*/
@RestController
@RequestMapping("/users")
@Slf4j
@Tag(name = "用户服务接口", description = "提供用户相关操作的接口")
public class UserController {/*** 模拟数据库存储用户信息*/private static final Map<Long, User> USER_MAP = new ConcurrentHashMap<>();/*** 当前服务端口*/@Value("${server.port}")private String serverPort;static {// 初始化测试数据User user1 = new User();user1.setId(1L);user1.setUsername("张三");user1.setAge(25);user1.setEmail("zhangsan@example.com");USER_MAP.put(1L, user1);User user2 = new User();user2.setId(2L);user2.setUsername("李四");user2.setAge(30);user2.setEmail("lisi@example.com");USER_MAP.put(2L, user2);}/*** 根据ID查询用户* * @param id 用户ID* @return 用户信息*/@GetMapping("/{id}")@Operation(summary = "根据ID查询用户", description = "根据用户ID查询用户详细信息")public User getUserById(@Parameter(description = "用户ID", required = true)@PathVariable Long id) {log.info("查询用户信息,ID: {}, 服务端口: {}", id, serverPort);User user = USER_MAP.get(id);return user;}/*** 创建用户* * @param user 用户信息* @return 创建的用户信息*/@PostMapping@Operation(summary = "创建用户", description = "创建新用户并返回用户信息")public User createUser(@Parameter(description = "用户信息", required = true)@RequestBody User user) {log.info("创建用户,用户信息: {}, 服务端口: {}", user, serverPort);USER_MAP.put(user.getId(), user);return user;}/*** 获取服务信息* * @return 服务信息*/@GetMapping("/service-info")@Operation(summary = "获取服务信息", description = "获取当前服务的信息,用于测试负载均衡")public Map<String, String> getServiceInfo() {Map<String, String> info = new HashMap<>(2);info.put("serviceName", "user-service");info.put("serverPort", serverPort);log.info("获取服务信息: {}", info);return info;}
}

5. 创建启动类

package com.example.nacosproviderexample;import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.info.Info;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;/*** Nacos服务提供者示例应用启动类* * @author ken*/
@SpringBootApplication
@EnableDiscoveryClient // 开启服务发现客户端功能
@OpenAPIDefinition(info = @Info(title = "用户服务API",version = "1.0.0",description = "用户服务的API文档")
)
public class NacosProviderExampleApplication {public static void main(String[] args) {SpringApplication.run(NacosProviderExampleApplication.class, args);}
}
4.2.2 服务消费者

1. 创建 Maven 项目,添加依赖

<?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><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.0</version><relativePath/></parent><groupId>com.example</groupId><artifactId>nacos-consumer-example</artifactId><version>1.0.0</version><name>nacos-consumer-example</name><description>Nacos Service Consumer Example</description><properties><java.version>17</java.version><spring-cloud-alibaba.version>2023.0.0.0</spring-cloud-alibaba.version></properties><dependencies><!-- Spring Boot Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Spring Cloud Alibaba Nacos Discovery --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!-- Spring Cloud OpenFeign --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!-- LoadBalancer --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency><!-- Lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.30</version><optional>true</optional></dependency><!-- Spring Boot Starter Test --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- Swagger3 --><dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-starter-webmvc-ui</artifactId><version>2.3.0</version></dependency><!-- Fastjson2 --><dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>fastjson2</artifactId><version>2.0.41</version></dependency></dependencies><dependencyManagement><dependencies><!-- Spring Cloud Alibaba --><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><!-- Spring Cloud --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>2023.0.0</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build>
</project>

2. 创建配置文件 application.properties

# 服务端口
server.port=8082# 服务名称
spring.application.name=order-service# Nacos服务发现地址
spring.cloud.nacos.discovery.server-addr=localhost:8848# 开启服务注册与发现
spring.cloud.nacos.discovery.enabled=true

3. 创建 Feign 客户端,调用用户服务

package com.example.nacosconsumerexample.feign;import com.example.nacosconsumerexample.entity.User;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;import java.util.Map;/*** 用户服务Feign客户端* * @author ken*/
@FeignClient(name = "user-service") // 指定要调用的服务名称
public interface UserServiceFeignClient {/*** 根据ID查询用户* * @param id 用户ID* @return 用户信息*/@GetMapping("/users/{id}")@Operation(summary = "根据ID查询用户", description = "调用用户服务根据ID查询用户")@Parameters({@Parameter(name = "id", description = "用户ID", in = ParameterIn.PATH, required = true)})User getUserById(@PathVariable("id") Long id);/*** 创建用户* * @param user 用户信息* @return 创建的用户信息*/@PostMapping("/users")@Operation(summary = "创建用户", description = "调用用户服务创建新用户")User createUser(@RequestBody User user);/*** 获取服务信息* * @return 服务信息*/@GetMapping("/users/service-info")@Operation(summary = "获取服务信息", description = "调用用户服务获取服务信息")Map<String, String> getServiceInfo();
}

4. 创建控制器 OrderController

package com.example.nacosconsumerexample.controller;import com.example.nacosconsumerexample.entity.User;
import com.example.nacosconsumerexample.feign.UserServiceFeignClient;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.HashMap;
import java.util.Map;/*** 订单服务控制器* * @author ken*/
@RestController
@RequestMapping("/orders")
@Slf4j
@Tag(name = "订单服务接口", description = "提供订单相关操作的接口")
public class OrderController {/*** 注入用户服务Feign客户端*/@Autowiredprivate UserServiceFeignClient userServiceFeignClient;/*** 创建订单* * @param userId 用户ID* @return 订单信息*/@PostMapping@Operation(summary = "创建订单", description = "创建新订单,需要调用用户服务获取用户信息")public Map<String, Object> createOrder(@Parameter(description = "用户ID", required = true)@RequestParam Long userId) {log.info("创建订单,用户ID: {}", userId);// 调用用户服务获取用户信息User user = userServiceFeignClient.getUserById(userId);if (user == null) {log.error("用户不存在,用户ID: {}", userId);Map<String, Object> result = new HashMap<>(2);result.put("success", false);result.put("message", "用户不存在");return result;}// 模拟创建订单Map<String, Object> order = new HashMap<>(4);order.put("id", System.currentTimeMillis());order.put("userId", userId);order.put("userName", user.getUsername());order.put("product", "示例商品");log.info("订单创建成功,订单信息: {}", order);Map<String, Object> result = new HashMap<>(2);result.put("success", true);result.put("data", order);return result;}/*** 测试负载均衡* * @return 服务信息*/@GetMapping("/load-balance-test")@Operation(summary = "测试负载均衡", description = "多次调用,测试负载均衡效果")public Map<String, String> loadBalanceTest() {log.info("测试负载均衡");return userServiceFeignClient.getServiceInfo();}
}

5. 创建启动类

package com.example.nacosconsumerexample;import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.info.Info;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;/*** Nacos服务消费者示例应用启动类* * @author ken*/
@SpringBootApplication
@EnableDiscoveryClient // 开启服务发现客户端功能
@EnableFeignClients // 开启Feign客户端功能
@OpenAPIDefinition(info = @Info(title = "订单服务API",version = "1.0.0",description = "订单服务的API文档")
)
public class NacosConsumerExampleApplication {public static void main(String[] args) {SpringApplication.run(NacosConsumerExampleApplication.class, args);}
}
4.2.3 运行与测试
  1. 启动 Nacos 服务器(单机模式)
  2. 启动用户服务(user-service),可以通过修改端口号启动多个实例:

    bash

    # 第一个实例,端口8081
    java -jar nacos-provider-example-1.0.0.jar --server.port=8081# 第二个实例,端口8083
    java -jar nacos-provider-example-1.0.0.jar --server.port=8083
    
  3. 启动订单服务(order-service)
  4. 访问 Nacos 控制台的服务管理,可以看到注册的服务和实例
  5. 访问订单服务的 Swagger UI:http://localhost:8082/swagger-ui/index.html
  6. 多次调用/orders/load-balance-test接口,观察返回的端口号是否在 8081 和 8083 之间切换,验证负载均衡效果
  7. 调用/orders接口,传入 userId=1,验证服务间调用是否正常

4.3 服务发现原理

Nacos 的服务发现机制主要包含服务注册、服务发现和健康检查三个核心过程:

  1. 服务注册

    • 服务启动时,会将自己的地址、端口、元数据等信息发送给 Nacos Server
    • Nacos Server 将这些信息存储起来,并返回注册成功的响应
  2. 服务发现

    • 消费者启动时,会向 Nacos Server 订阅它需要调用的服务
    • Nacos Server 返回该服务的所有可用实例列表
    • 消费者将实例列表缓存到本地,用于后续的服务调用
    • 当服务实例发生变化(新增、下线、健康状态变化)时,Nacos Server 会主动推送变更给消费者
    • 消费者收到变更通知后,更新本地缓存的实例列表
  3. 健康检查

    • Nacos Server 会定期向服务实例发送健康检查请求
    • 服务实例返回自己的健康状态
    • 如果服务实例不健康,Nacos Server 会将其标记为不健康,不再将其推荐给消费者

4.4 服务路由与负载均衡

Nacos 结合 Spring Cloud LoadBalancer 提供了服务路由和负载均衡功能。默认的负载均衡策略是轮询,我们也可以根据需要自定义负载均衡策略。

4.4.1 自定义负载均衡策略

创建一个基于权重的负载均衡策略:

package com.example.nacosconsumerexample.config;import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.loadbalancer.core.RandomLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;/*** 负载均衡配置* * @author ken*/
@Configuration
@Slf4j
public class LoadBalancerConfig {/*** 自定义基于权重的负载均衡器* * @param environment 环境变量* @param loadBalancerClientFactory 负载均衡客户端工厂* @return 基于权重的负载均衡器*/@Beanpublic ReactorLoadBalancer<ServiceInstance> weightLoadBalancer(Environment environment, LoadBalancerClientFactory loadBalancerClientFactory) {String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);log.info("为服务 {} 配置基于权重的负载均衡策略", name);return new WeightedLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name);}
}

实现权重负载均衡器:

package com.example.nacosconsumerexample.config;import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import reactor.core.publisher.Mono;import java.util.List;
import java.util.Random;/*** 基于权重的负载均衡器* * @author ken*/
@Slf4j
public class WeightedLoadBalancer extends org.springframework.cloud.loadbalancer.core.RandomLoadBalancer {private final String serviceId;private final Random random = new Random();/*** 构造函数* * @param serviceInstanceListSupplierProvider 服务实例列表提供者* @param serviceId 服务ID*/public WeightedLoadBalancer(ServiceInstanceListSupplier serviceInstanceListSupplierProvider, String serviceId) {super(serviceInstanceListSupplierProvider, serviceId);this.serviceId = serviceId;}/*** 选择服务实例* * @return 选中的服务实例*/@Overridepublic Mono<ServiceInstance> choose() {return getInstanceSupplier().get().next().map(this::getWeightedInstance);}/*** 根据权重选择服务实例* * @param instances 服务实例列表* @return 选中的服务实例*/private ServiceInstance getWeightedInstance(List<ServiceInstance> instances) {if (instances.isEmpty()) {log.warn("服务 {} 没有可用实例", serviceId);return null;}// 计算总权重int totalWeight = 0;for (ServiceInstance instance : instances) {totalWeight += getWeight(instance);}// 随机生成一个0到总权重之间的数int randomWeight = random.nextInt(totalWeight);// 根据权重选择实例int currentWeight = 0;for (ServiceInstance instance : instances) {currentWeight += getWeight(instance);if (currentWeight > randomWeight) {log.info("选择服务实例: {}:{},权重: {}", instance.getHost(), instance.getPort(), getWeight(instance));return instance;}}// 如果出现意外情况,默认返回第一个实例return instances.get(0);}/*** 获取服务实例的权重* * @param instance 服务实例* @return 权重值,默认为1*/private int getWeight(ServiceInstance instance) {try {String weightStr = instance.getMetadata().get("weight");if (weightStr != null) {return Integer.parseInt(weightStr);}} catch (Exception e) {log.warn("获取服务实例 {}:{} 的权重失败", instance.getHost(), instance.getPort(), e);}return 1;}
}

在启动类上指定负载均衡配置:

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@LoadBalancerClient(name = "user-service", configuration = LoadBalancerConfig.class
)
public class NacosConsumerExampleApplication {// ...
}

4.5 服务健康检查

Nacos 提供了多种健康检查方式,确保只有健康的服务实例会被消费者调用:

  1. 客户端主动上报:服务实例定期向 Nacos Server 发送心跳,报告自己的健康状态
  2. 服务器主动检测:Nacos Server 定期向服务实例发送健康检查请求

可以在配置文件中自定义健康检查相关参数:

# 健康检查类型:client(客户端上报)、server(服务器检测)
spring.cloud.nacos.discovery.heart-beat-type=client# 客户端心跳间隔时间(毫秒)
spring.cloud.nacos.discovery.heart-beat-interval=5000# 服务器健康检查超时时间(毫秒)
spring.cloud.nacos.discovery.heart-beat-timeout=15000# 服务实例健康检查路径(服务器检测模式下使用)
spring.cloud.nacos.discovery.health-check-path=/actuator/health# 服务实例健康检查端口
spring.cloud.nacos.discovery.health-check-port=${server.port}# 服务实例健康检查协议
spring.cloud.nacos.discovery.health-check-http-method=GET

五、Nacos 高级特性

5.1 服务元数据

服务元数据是附加在服务或实例上的键值对信息,可以用来存储服务的额外信息,如版本号、权重、环境等。

5.1.1 配置服务元数据

可以在配置文件中配置服务实例的元数据:

# 服务元数据
spring.cloud.nacos.discovery.metadata.version=1.0
spring.cloud.nacos.discovery.metadata.weight=10
spring.cloud.nacos.discovery.metadata.env=dev
spring.cloud.nacos.discovery.metadata.region=east
5.1.2 获取服务元数据

在服务消费者中,可以通过DiscoveryClient获取服务实例的元数据:

package com.example.nacosconsumerexample.controller;import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** 服务元数据控制器* * @author ken*/
@RestController
@RequestMapping("/metadata")
@Slf4j
public class MetadataController {@Autowiredprivate DiscoveryClient discoveryClient;/*** 获取用户服务的元数据* * @return 服务实例及其元数据*/@GetMapping("/user-service")public Map<String, Object> getUserServiceMetadata() {List<ServiceInstance> instances = discoveryClient.getInstances("user-service");Map<String, Object> result = new HashMap<>(2);result.put("serviceName", "user-service");result.put("instances", instances.stream().map(instance -> {Map<String, Object> instanceInfo = new HashMap<>(4);instanceInfo.put("host", instance.getHost());instanceInfo.put("port", instance.getPort());instanceInfo.put("metadata", instance.getMetadata());return instanceInfo;}).toList());log.info("获取用户服务元数据: {}", result);return result;}
}

5.2 服务限流

Nacos 结合 Sentinel 可以实现服务限流功能,保护服务不被流量峰值击垮。

5.2.1 添加依赖
<!-- Spring Cloud Alibaba Sentinel -->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency><!-- Sentinel 数据源 -->
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
5.2.2 配置限流规则

在 Nacos 控制台添加限流规则配置:

  • Data ID: sentinel-rules.json
  • Group: DEFAULT_GROUP
  • 配置内容:
[{"resource": "GET:/users/{id}","limitApp": "default","grade": 1,"count": 5,"strategy": 0,"controlBehavior": 0,"clusterMode": false}
]
5.2.3 配置应用
# Sentinel 控制台地址
spring.cloud.sentinel.transport.dashboard=localhost:8080# 限流规则数据源配置
spring.cloud.sentinel.datasource.ds1.nacos.server-addr=localhost:8848
spring.cloud.sentinel.datasource.ds1.nacos.data-id=sentinel-rules.json
spring.cloud.sentinel.datasource.ds1.nacos.group-id=DEFAULT_GROUP
spring.cloud.sentinel.datasource.ds1.nacos.data-type=json
spring.cloud.sentinel.datasource.ds1.rule-type=flow
5.2.4 实现限流降级处理
package com.example.nacosproviderexample.controller;import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.example.nacosproviderexample.entity.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** 带限流功能的用户控制器* * @author ken*/
@RestController
@RequestMapping("/users-with-sentinel")
@Slf4j
public class UserWithSentinelController {/*** 根据ID查询用户,带有限流保护* * @param id 用户ID* @return 用户信息*/@GetMapping("/{id}")@SentinelResource(value = "GET:/users/{id}",blockHandler = "getUserByIdBlockHandler")public User getUserById(@PathVariable Long id) {// 模拟查询用户User user = new User();user.setId(id);user.setUsername("示例用户");user.setAge(25);user.setEmail("example@test.com");return user;}/*** 限流降级处理方法* * @param id 用户ID* @param ex 限流异常* @return 降级返回的用户信息*/public User getUserByIdBlockHandler(Long id, BlockException ex) {log.warn("查询用户被限流,用户ID: {}", id, ex);User user = new User();user.setId(id);user.setUsername("限流保护");user.setAge(0);user.setEmail("limited@test.com");return user;}
}

5.3 Nacos 与 Spring Cloud Gateway 集成

Spring Cloud Gateway 是 Spring Cloud 生态中的网关组件,与 Nacos 结合可以实现动态路由。

5.3.1 创建网关项目,添加依赖
<?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><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.0</version><relativePath/></parent><groupId>com.example</groupId><artifactId>nacos-gateway-example</artifactId><version>1.0.0</version><name>nacos-gateway-example</name><description>Nacos Gateway Example</description><properties><java.version>17</java.version><spring-cloud-alibaba.version>2023.0.0.0</spring-cloud-alibaba.version></properties><dependencies><!-- Spring Cloud Gateway --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!-- Spring Cloud Alibaba Nacos Discovery --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!-- Spring Cloud Alibaba Nacos Config --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><!-- Lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.30</version><optional>true</optional></dependency></dependencies><dependencyManagement><dependencies><!-- Spring Cloud Alibaba --><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><!-- Spring Cloud --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>2023.0.0</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build>
</project>
5.3.2 创建配置文件 bootstrap.properties
# 服务端口
server.port=8080# 服务名称
spring.application.name=api-gateway# Nacos配置中心地址
spring.cloud.nacos.config.server-addr=localhost:8848# Nacos服务发现地址
spring.cloud.nacos.discovery.server-addr=localhost:8848# 配置文件的Data ID
spring.cloud.nacos.config.name=gateway-routes# 配置文件的Group
spring.cloud.nacos.config.group=GATEWAY_GROUP# 配置文件的格式
spring.cloud.nacos.config.file-extension=json# 开启配置自动刷新
spring.cloud.nacos.config.refresh-enabled=true
5.3.3 在 Nacos 控制台创建网关路由配置
  • Data ID: gateway-routes.json
  • Group: GATEWAY_GROUP
  • 配置内容:
{"spring": {"cloud": {"gateway": {"routes": [{"id": "user-service-route","uri": "lb://user-service","predicates": ["Path=/api/users/**"],"filters": ["StripPrefix=1"]},{"id": "order-service-route","uri": "lb://order-service","predicates": ["Path=/api/orders/**"],"filters": ["StripPrefix=1"]}]}}}
}
5.3.4 创建启动类
package com.example.nacosgatewayexample;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;/*** Nacos网关示例应用启动类* * @author ken*/
@SpringBootApplication
@EnableDiscoveryClient
public class NacosGatewayExampleApplication {public static void main(String[] args) {SpringApplication.run(NacosGatewayExampleApplication.class, args);}
}
5.3.5 测试网关路由
  1. 启动 Nacos、用户服务、订单服务和网关服务
  2. 通过网关访问用户服务:http://localhost:8080/api/users/1
  3. 通过网关访问订单服务:http://localhost:8080/api/orders?userId=1
  4. 在 Nacos 控制台修改路由配置,测试动态路由效果

六、Nacos 生产环境部署与优化

6.1 集群部署最佳实践

在生产环境中,为了保证高可用性,Nacos 需要部署为集群模式:

  1. 服务器要求

    • 至少 3 台服务器(推荐 4 核 8G 以上配置)
    • 服务器之间网络互通
    • 时间同步
  2. 数据库配置

    • 使用 MySQL 主从架构或集群
    • 配置连接池参数,优化数据库性能
    • 定期备份数据库
  3. Nacos 配置

    • 配置集群节点信息(cluster.conf)
    • 调整 JVM 参数,推荐配置:
      -Xms2g -Xmx2g -Xmn1g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m
      
    • 配置日志滚动策略,避免磁盘空间耗尽
  4. 负载均衡

    • 在 Nacos 集群前部署负载均衡器(如 Nginx、SLB 等)
    • 配置健康检查,自动剔除不健康节点
  5. 安全配置

    • 开启 Nacos 认证功能
    • 配置网络访问控制,限制访问来源
    • 敏感配置加密存储

6.2 性能优化

为了提高 Nacos 的性能,可以从以下几个方面进行优化:

  1. JVM 优化

    • 根据服务器配置调整 JVM 参数
    • 启用 G1 垃圾收集器
    • 配置合适的新生代和老年代比例
  2. 数据库优化

    • 为 Nacos 数据库表创建合适的索引
    • 调整 MySQL 配置,如innodb_buffer_pool_size
    • 定期清理过期数据
  3. 缓存优化

    • 调整 Nacos 本地缓存大小
    • 配置合理的缓存过期时间
  4. 网络优化

    • 使用长连接减少连接建立开销
    • 调整 TCP 参数,如net.ipv4.tcp_tw_reuse
  5. 配置优化

    • 合理设置服务健康检查间隔
    • 批量处理配置变更通知

6.3 监控与告警

为了及时发现和解决问题,需要对 Nacos 进行监控和告警:

  1. 监控指标

    • 服务注册 / 发现次数
    • 配置变更次数
    • 健康检查成功率
    • JVM 内存使用情况
    • 数据库连接池状态
  2. 监控工具

    • Prometheus + Grafana:收集和展示监控指标
    • Spring Boot Actuator:暴露 Nacos 的监控端点
    • ELK Stack:收集和分析日志
  3. 告警配置

    • 服务健康检查失败告警
    • 内存使用率过高告警
    • 数据库连接数过高告警
    • 接口响应时间过长告警

七、常见问题与解决方案

7.1 服务注册失败

问题现象:服务启动后,在 Nacos 控制台看不到服务实例。

可能原因及解决方案

  1. 网络问题

    • 检查 Nacos 服务器地址是否正确
    • 检查防火墙是否开放 Nacos 端口(默认 8848)
    • 检查服务与 Nacos 服务器之间的网络连通性
  2. 配置问题

    • 检查是否添加了spring-cloud-starter-alibaba-nacos-discovery依赖
    • 检查是否添加了@EnableDiscoveryClient注解
    • 检查spring.cloud.nacos.discovery.enabled是否设置为 true
  3. 版本兼容性

    • 检查 Spring Cloud Alibaba 与 Spring Boot 版本是否兼容
    • 推荐使用官方文档中的版本组合

7.2 配置无法动态刷新

问题现象:在 Nacos 控制台修改配置后,应用中没有获取到最新配置。

可能原因及解决方案

  1. 未开启刷新功能

    • 在需要刷新的 Bean 上添加@RefreshScope注解
    • 检查spring.cloud.nacos.config.refresh-enabled是否设置为 true
  2. 配置监听问题

    • 检查配置的 Data ID、Group 是否正确
    • 检查命名空间是否正确
  3. 缓存问题

    • 检查本地缓存是否过期
    • 尝试重启应用,清除缓存

7.3 服务调用失败

问题现象:消费者调用服务提供者时失败。

可能原因及解决方案

  1. 服务发现问题

    • 检查服务名称是否正确
    • 检查服务是否已注册到 Nacos
    • 检查服务实例是否健康
  2. 网络问题

    • 检查服务之间的网络连通性
    • 检查服务端口是否正确
  3. 负载均衡问题

    • 检查是否添加了负载均衡依赖
    • 检查负载均衡配置是否正确

八、总结与展望

Nacos 作为一款优秀的服务发现和配置管理中间件,为微服务架构提供了强大的支持。通过本文的介绍,我们了解了 Nacos 的核心概念、架构设计、使用方法和最佳实践。

Nacos 的主要优势包括:

  1. 功能丰富:集服务发现和配置管理于一体,满足微服务架构的核心需求
  2. 易用性高:提供简洁的 API 和直观的控制台,降低使用门槛
  3. 性能优异:经过阿里巴巴内部大规模验证,性能稳定可靠
  4. 扩展性强:支持集群部署,可根据需求横向扩展
  5. 生态完善:与 Spring Cloud、Dubbo 等主流框架无缝集成

随着云原生技术的发展,Nacos 也在不断演进,未来可能会在以下方面进行增强:

  1. 更好的云原生支持:与 Kubernetes 等容器编排平台深度集成
  2. 更丰富的流量管理功能:提供更细粒度的流量控制能力
  3. 更强的安全性:增强认证、授权和加密功能
  4. 更高的性能:持续优化性能,支持更大规模的服务集群

掌握 Nacos 对于微服务开发者来说至关重要,它不仅能帮助我们解决实际开发中的问题,还能让我们更深入地理解微服务架构的核心思想。希望本文能为你学习和使用 Nacos 提供有益的参考。

参考资料

  1. Nacos 官方文档
  2. Spring Cloud Alibaba 官方文档
  3. 《Spring Cloud Alibaba 微服务实战》
  4. Nacos GitHub 仓库
http://www.dtcms.com/a/394022.html

相关文章:

  • 基于DrissionPage的趣易百影院数据采集实战指南
  • github十大开源FPGA项目
  • R语言 csv新增一列 dplyr操作
  • IDEA创建Module子项目后,只有一个普通的文件夹
  • 支持向量机深度解析:从数学原理到工程实践的完整指南
  • 2025华为杯研究生数学建模竞赛B题及求解思路
  • 三星CIS全球产能布局解析:本土根基、海外扩张与策略雄心
  • js集装箱号校验算法
  • 【机器学习】最优传输(OT)和 KL散度的区别
  • 推荐一个随机生成图片的网站: Lorem Picsum
  • APE自动化提示词工程
  • 探究某黄鱼x-sign生成算法——终极篇
  • 霍尔传感器安装错位下的FOC控制:线性插值与锁相环(PLL)算法的抉择
  • FFmpeg 深入精讲(三)FFmpeg 中级开发
  • AI驱动下的蛋白质设计
  • ARM基本汇编操作指令
  • 电商搜索 API 的优化与性能提升:从瓶颈突破到体验升级
  • 使用DeepSeek辅助测试一个rust编写的postgresql协议工具包convergence
  • 【00】EPGF 架构搭建教程之 总揽篇
  • 深度剖析 vector 底层原理:从手写实现到核心技术点全解析
  • 嵌入式开发学习日志29——stm32之定时器中断
  • 通俗范畴论17.3 向量空间的对偶与双对偶
  • 表格 表头增加悬浮提示内容
  • emacs段落重排快捷键
  • 第九届人单合一模式引领论坛举行 构建AI时代的智能交互生态
  • 不用搜驱动!惠普官方工具:自动适配,坏了直接重装
  • JAVA八股文——java虚拟机栈
  • 华为MindSpeed 训练加速库:架构解析
  • Java的Stream实现对list实用操作【持续更新】
  • 【AI智能体】Dify集成 Echarts实现数据报表展示实战详解