Spring Colud Alibaba Nacos微服务组件的使用教程

Nacos官网

什么是nacos

Dynamic Naming and Configuration Service(动态命名和配置服务)

nacos可以作为服务注册中心

nacos可以作为配置中心

nacos即支持AP也支持CP

下载安装Nacos

下载地址:https://github.com/alibaba/nacos/releases/download/2.5.0/nacos-server-2.5.0.zip

解压后,进入bin目录

通过"startup.cmd -m standalone"脚本启动,以单机模式启动

# 单机模式(开发环境)
startup.cmd -m standalone

# 集群模式(生产环境)
startup.cmd -m cluster

默认的运行端口为8848,默认的登陆账户是nacos,默认密码是nacos

访问http://localhost:8848/nacos验证nacos启动成功

nacos注册中心案例

在微服务项目父模块依赖管理中引入公共依赖,指定版本

   <!--以pom依赖的形式导入spring-cloud-alibaba-dependencies依赖-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2021.0.5.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

分别在各个微服务模块引入nacos的服务发现模块

        <!--引入nacos的服务发现依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

分别在各个微服务模块中配置naocs

spring:
  application:
    name: member-consumer
  cloud:
    nacos:
      discovery:
        #配置nacos服务注册中心的地址
        server-addr: localhost:8848

分别在各个微服务中使用注解"@EnableDiscoveryClient"启用服务发现功能

package anyi.space.memberConsumer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

/**
 * @ProjectName: distributedSystemLearn
 * @FileName: MemberConsumerApplication
 * @Author: 杨逸
 * @Data:2025/4/13 20:05
 * @Description:
 */
@EnableDiscoveryClient
@SpringBootApplication(exclude= DataSourceAutoConfiguration.class)
public class MemberConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(MemberConsumerApplication.class,args);
    }
}

启动各个微服务,在浏览器中访问http://localhost:8848/nacos查看nacos的管理面板,验证各个微服务是否成功注册到nacos注册中心

服务消费方利用nacos注册中心通过服务名称消费服务提供方

在服务消费方导入LoadBanlcer依赖

        <!--新版的nacos负载均衡组件使用的是LoadBalancer,旧版使用的是Ribbon-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
            <version>3.1.5</version>
        </dependency>

使用RestTemplate进行远程调用,默认的负载均衡算法是轮询

注入一个RestTemplate

package anyi.space.memberConsumer.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * @ProjectName: distributedSystemLearn
 * @FileName: RestTemplateConfig
 * @Author: 杨逸
 * @Data:2025/4/13 20:06
 * @Description:
 */
@Configuration
public class RestTemplateConfig {
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

远程调用使用服务名称

package anyi.space.memberConsumer.service.impl;

import anyi.sapce.common.entity.Member;
import anyi.sapce.common.entity.ResponseResult;
import anyi.space.memberConsumer.service.MemberService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.Map;

/**
 * @ProjectName: distributedSystemLearn
 * @FileName: MemberServiceIml
 * @Author: 杨逸
 * @Data:2025/4/13 20:10
 * @Description:
 */
@RequiredArgsConstructor
@Service
public class MemberServiceIml implements MemberService {
    private final RestTemplate restTemplate;
    //基本的服务名
    public static final String BASE_URL = "http://member-service-provider";
    @Override
    public ResponseResult getById(Long id) {
        /**
         * 使用服务名通过RestTemplate调用远程服务
         */
        ResponseEntity<ResponseResult> resultResponseEntity = restTemplate.getForEntity(BASE_URL + "/member-provider/member?id="+id, ResponseResult.class);
        return resultResponseEntity.getBody();
    }

    @Override
    public boolean save(Member member) {
        //直接传递参数,是使用json的格式提交数据
        ResponseEntity<ResponseResult> responseResultResponseEntity = restTemplate.postForEntity(BASE_URL + "/member-provider/member", member, ResponseResult.class);
        //HttpEntity<String> stringHttpEntity = new HttpEntity<>();
        Object data = responseResultResponseEntity.getBody().getData();
        boolean flag = (boolean) data;
        return flag;
    }
}

通过postman验证可以正确通过服务名称调用服务,且是负载均衡算法是轮询的

nacos负载均衡

新版的nacos使用的LoadBalancer进行负载均衡,旧版使用的是Ribbon

Nacos中AP和CP的切换

Nacos中AP和CP的切换的参考文章

分布式系统中的三大原则,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性)

Nacos默认使用的是AP模式

AP:数据强一致性,服务不一定可用

CP:服务一定可用,数据会短暂不一致,但数据是最终一致

使用Nacos开放的RestAPI进行切换,注意使用PUT请求方式进行调用

  • 切换为AP模式
curl -X PUT http://localhost:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=AP

  • 切换为CP模式
curl -X PUT http://localhost:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP

nacos配置中心案例

官方文档

  • 在微服务模块中导入nacos配置中心的依赖
        <!--nacos配置中心依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
  • 在bootstarp.yaml配置文件中配置nacos配置中心的地址

    • 在Spring Cloud 2020.0.2版本后,bootstarp.yaml配置配置文件被禁用了,需要引入依赖
            <!--在新版的springcloud应用中使用bootstarp配置文件,需要引入这个依赖-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-bootstrap</artifactId>
                <version>3.1.5</version>
            </dependency>
    
    • 通过"spring.cloud.nacos.config.server-addr"配置nacos配置中心服务的地址
    • 通过"spring.cloud.nacos.config.file-extension"配置匹配nacos配置中心配置文件的后缀
    • 通过"spring.cloud.nacos.config.prefix"配置匹配nacos配置中心配置文件的前缀
    • 配置中心的DataId匹配格式为:${spring.cloud.nacos.config.prefix}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
    • nacos配置中心中通过namespace(名称空间),group(分组),dataId(配置id)三者唯一标识一个配置
server:
  port: 5000
  servlet:
    context-path: /nacos-config-client
spring:
  cloud:
    nacos:
      discovery:
        #注册中心服务地址
        server-addr: localhost:8848
      #匹配nacos配置中心中DataId为: ${spring.cloud.nacos.config.prefix}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} 的配置文件
      config:
        #配置中心服务地址
        server-addr: localhost:8848
        #配置文件后缀
        file-extension: yaml
        #配置文件前缀,默认值为spring.application.name
        prefix: ${spring.application.name}
        #配置分组名称,默认为:DEFAULT_GROUP
        group: DEFAULT_GROUP
        #配置文件命名空间,默认为:public
        namespace: public
  application:
    name: nacos-config-client

  • 在application.yaml配置使用哪个环境的配置
    • 通过"spring.profiles.active"参数配置使用哪个环境的配置文件
    • test表示测试环境
    • dev表示开发环境
    • prod表示生产环境
    • springboot中配置文件的加载是存在优先级顺序的,bootstrap.yml优先级高于application.yml
spring:
  profiles:
    #使用哪个环境的配置文件
    #test:测试环境,dev:开发环境,prod:生产环境
    active: test
  • 在nacos配置中心创建配置,使用yaml格式,注意dataId要与客户端配置中的${spring.cloud.nacos.config.prefix}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}保持一致
config:
    info: 杨逸在学nacos的配置中心
    name: 配置中心

  • 创建一个测试Controller,验证成功从nacos配置中心中拉取配置信息
    • 使用"@Value"注解从配置中获取信息
    • 使用"@RefreshScope"注解配置自动刷新配置,当配置中心的配置发生变更时,运行的springboot程序能自动更新配置的值
package space.anyi.nacosConfigClient.controller;

import com.alibaba.nacos.api.config.annotation.NacosValue;
import lombok.Data;
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;

/**
 * @ProjectName: distributedSystemLearn
 * @FileName: NacosConfigClientController
 * @Author: 杨逸
 * @Data:2025/9/14 18:02
 * @Description: 测试nacos配置中心的controller
 */
@Data
@RestController()
@RequestMapping("/config")
//@RefreshScope表示自动刷新配置,配合配置中心实现配置的动态刷新
@RefreshScope
public class NacosConfigClientController {
    @Value("${config.info}")
    private String configInfo;
    @Value("${config.name}")
    private String configName;

    @GetMapping("/info")
    public String getConfigInfo(){
        return configInfo;
    }
    @GetMapping("/name")
    public String getConfigName(){
        return configName;
    }
}

  • 使用postman接口测试验证,拉取nacos配置中心的配置成功

Nacos配置隔离方案

flowchart TD
    subgraph Nacos配置管理系统
        N1[Namespace: 公司A]
        N2[Namespace: 公司B]
        
        subgraph N1_Sub [公司A内部配置]
            G1[Group: 前端组]
            G2[Group: 后端组]
            G3[Group: 移动端组]
            
            subgraph G1_Sub [前端组配置]
                D1[DataId: 开发环境]
                D2[DataId: 测试环境]
                D3[DataId: 生产环境]
            end
            
            subgraph G2_Sub [后端组配置]
                D4[DataId: 开发环境]
                D5[DataId: 测试环境]
                D6[DataId: 生产环境]
            end
            
            subgraph G3_Sub [移动端组配置]
                D7[DataId: 开发环境]
                D8[DataId: 测试环境]
                D9[DataId: 生产环境]
            end
        end
        
        subgraph N2_Sub [公司B内部配置]
            G4[Group: 前端组]
            G5[Group: 后端组]
            G6[Group: 大数据组]
            
            subgraph G4_Sub [前端组配置]
                D10[DataId: 开发环境]
                D11[DataId: 测试环境]
                D12[DataId: 生产环境]
            end
            
            subgraph G5_Sub [后端组配置]
                D13[DataId: 开发环境]
                D14[DataId: 测试环境]
                D15[DataId: 生产环境]
            end
            
            subgraph G6_Sub [大数据组配置]
                D16[DataId: 开发环境]
                D17[DataId: 测试环境]
                D18[DataId: 生产环境]
            end
        end
    end
    
    N1 --> N1_Sub
    N2 --> N2_Sub
    
    G1 --> G1_Sub
    G2 --> G2_Sub
    G3 --> G3_Sub
    G4 --> G4_Sub
    G5 --> G5_Sub
    G6 --> G6_Sub
    
    %% 样式设置
    classDef namespace fill:#bbdefb,stroke:#1e88e5,stroke-width:2px;
    classDef group fill:#e1bee7,stroke:#8e24aa,stroke-width:2px;
    classDef dataid fill:#c8e6c9,stroke:#43a047,stroke-width:2px;
    
    class N1,N2 namespace;
    class G1,G2,G3,G4,G5,G6 group;
    class D1,D2,D3,D4,D5,D6,D7,D8,D9,D10,D11,D12,D13,D14,D15,D16,D17,D18 dataid;

naocs中有三种方式进行配置隔离,第一种是DataId,第二种是Group(分组),第三种是NameSpace(命名空间)

一般DataId的隔离场景是在同一个项目中,用于区分开发,测试,生产三种不同环境使用的配置

Group(分组隔离)的应用场景是在同一个企业中的不项目组中

NameSpace(命名空间)隔离的使用场景是在不同的企业与企业之间

基于DataId的配置隔离

  • 在nacos创建一个新的dev配置

    config:
        info: 学习基于DataId的配置隔离方案
        name: 基于DataId的配置隔离 
    
  • 在nacos客户端配置

    spring:
      profiles:
        #使用哪个环境的配置文件
        #test:测试环境,dev:开发环境,prod:生产环境
        active: dev
    
  • 通过postman测试

基于Group(分组)的配置隔离

  • 在nacos配置中心中创建一个新的测试配置

    • 在Group中填入"GROUP_YANGYI",创建一个新的分组

    config:
        info: 杨逸在学nacos的基于分组的配置隔离
        name: 基于分组隔离的配置中心
    
  • 在nacos客户端中配置分组信息

    • 通过"spring.cloud.nacos.config.group"参数配置分组信息
    server:
      port: 5000
      servlet:
        context-path: /nacos-config-client
    spring:
      cloud:
        nacos:
          discovery:
            #注册中心服务地址
            server-addr: localhost:8848
          #匹配nacos配置中心中DataId为: ${spring.cloud.nacos.config.prefix}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} 的配置文件
          config:
            #配置中心服务地址
            server-addr: localhost:8848
            #配置文件后缀
            file-extension: yaml
            #配置文件前缀,默认值为spring.application.name
            prefix: ${spring.application.name}
            #配置分组名称,默认为:DEFAULT_GROUP
            group: GROUP_YANGYI
            #配置文件命名空间,默认为:public
            namespace: public
      application:
        name: nacos-config-client
    
    
  • 通过postman测试

基于NameSpace(命名空间)的配置隔离

  • 在nacos中创建一个新的命名空间"yangyi"

  • 注意namespace的ID,在nacos配置namespace时需要使用到

  • 切换到"yangyi"的namespace(命名空间)

  • 命名空间"yangyi"中新建一个测试配置

  • 在nacos客户端配置namespace(命名空间)

    • 通过"spring.cloud.nacos.config.namespace"参数配置分组信息,注意配置namespace时,除了默认的public,其他的namespace配置使用的是namespace的ID
    server:
      port: 5000
      servlet:
        context-path: /nacos-config-client
    spring:
      cloud:
        nacos:
          discovery:
            #注册中心服务地址
            server-addr: localhost:8848
          #匹配nacos配置中心中DataId为: ${spring.cloud.nacos.config.prefix}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} 的配置文件
          config:
            #配置中心服务地址
            server-addr: localhost:8848
            #配置文件后缀
            file-extension: yaml
            #配置文件前缀,默认值为"spring.application.name"参数的值
            prefix: ${spring.application.name}
            #配置分组名称,默认为:DEFAULT_GROUP
            group: DEFAULT_GROUP
            #配置文件命名空间,默认为:public,配置其他的namespace时,使用的namespace的ID
            namespace: 0901089c-92c1-40fa-bf3c-b98d434061bc
      application:
        name: nacos-config-client
    
    
  • 通过postman测试