8. SpringCloud Alibaba Nacos 注册中心 + 配置中心 Nacos “分类配置” 超超详细使用+配置解析

526 阅读14分钟

8. SpringCloud Alibaba Nacos 注册中心 + 配置中心 Nacos “分类配置” 超超详细使用+配置解析

@[toc]

前言

1. Spring Cloud Alibaba Nacos 概述

Spring Cloud Alibaba Nacos 官网地址:github.com/alibaba/Nac…

在这里插入图片描述

Nacos 是什么:

一句话:Nacos 就是注册中心[替代 Eureka] + 配置中心[替代 Config] ,简单的说:Nacos 和 Eureka 是一样的

Nacos : Dynamic Naming and Configuration Service

Nacos: 架构理论基础: CAP理论(支持AP和CP,可以切换)

1.2 安装 Spring Cloud Alibaba Nacos + 运行

下载: github.com/alibaba/nac…

在这里插入图片描述

解压,运行 bin/startup.cmd 即可。 在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

浏览器访问:http://localhost:8848/nacos

用户名和密码都是: nacos

在这里插入图片描述

特别注意:Nacos 是作为一个微服务独立运行的,想要使用 Nacos 的时候,不可以将命名控制台,关闭了,关闭了也就是将 Nacos 给关闭了

2. 创建 Spring Cloud Alibaba Nacos 服务实例(Nacos 作为注册中心)

2.1 创建 Nacos 服务提供者

在这里插入图片描述

创建 member-service-nacos-provider-10004 并注册到 NacosServer8848

  1. 参考 member-service-provider-10000 来创建 member-service-nacos-provider-10004 即 可
  2. 创 建 好 后 , 使 用 member-service-provider-10000 的 源 码 和 配 置 替 换 member-service-nacos-provider-10004 生成的代码
  3. 提醒,拷贝时不要忘记拷贝 resources/mapper/MemberMapper.xml 这些 xxx.xml 文 件
  1. 修改父项目 pom.xml 。导入 Naocs 依赖的 jar 。可以参考官网文档:spring-cloud-alibaba-group.github.io/github-page…

在这里插入图片描述

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2.1.0.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

在这里插入图片描述

  1. 修改 pom.xml, 加入 spring-cloud-alibaba 依赖 在这里插入图片描述
         <!--            配置 Spring Cloud Alibaba-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.1.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
  1. 创建 member-service-nacos-provider-10004 当中的 resources 类路径下,创建 application.yml, 同时在其中编写 Nacos 的相关配置。如下图所示:

在这里插入图片描述

在这里插入图片描述

spring:
  application:
    name: member-service-nacos-provider # 配置应用的名称
    # 配置 nacos
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 # 配置注册到哪个 Nacos Server的地址
# 配置暴露所有的监控点:
management:
  endpoints:
    web:
      exposure:
        include: '*'

完整的 yaml 的编写:

server:
  port: 10004
spring:
  application:
    name: member-service-nacos-provider # 配置应用的名称
    # 配置 nacos
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 # 配置注册到哪个 Nacos Server的地址
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource # 配置 alibaba 的数据库连接池
    password: MySQL123
    username: root
    url: jdbc:mysql://localhost:3306/e_commerce_center_db?useSSL=true&useUnicode=true&characterEncoding=UTF-8

mybatis:
  mapper-locations: classpath:mapper/*.xml # 指定 mapper.xml 文件位置 classpath 表示 resources 目录下
  type-aliases-package: com.rainbowsea.springcloud.entity # 实例 bean 类所在的包,这样可以通过类名的方式

# 配置暴露所有的监控点:
management:
  endpoints:
    web:
      exposure:
        include: '*'

  1. 创建主启动类:创建主启动类 MemberNacosProviderApplication10004

在这里插入图片描述

特别说明:必须在主启动(场景启动器)类上加上@EnableDiscoveryClient 注解(引用Nacos发现注解),才能启动使用上 Nacos 注册中心

package com.rainbowsea.springcloud;


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


//@EnableDiscoveryClient  标注引入的是 Nacos 发现注解
@EnableDiscoveryClient
@SpringBootApplication
public class MemberApplication10004 {

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

  1. 为看到更好提示,修改 Controller。

修改 com/rainbowsea/springcloud/controller/MemberController.java 的输出信息。

在这里插入图片描述

在这里插入图片描述

package com.rainbowsea.springcloud.controller;


import com.rainbowsea.springcloud.entity.Member;
import com.rainbowsea.springcloud.entity.Result;
import com.rainbowsea.springcloud.service.MemberService;
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.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

@RestController
@Slf4j
public class MemberController {

    @Resource
    private MemberService memberService;


    /*
    说明:
         1. 我们的前端如果是以 json 格式来发送添加信息的Member,那么我们需要使用 @RequestBody
         才能将数据封装到对应的 bean,同时保证http的请求的 content-type 是对应
         2. 如果前端是以表单形式提交了,则不需要使用@RequestBody,才会进行对象bean参数封装,同时
         保证 http的请求的 content-type 是对应
     */

    /**
     * 添加方法/接口
     *
     * @param member
     * @return
     */
    @PostMapping("/member/save")
    public Result save(@RequestBody Member member) {
        // 注意:微服务组件通信的坑点:
        // 这里我们使用 RestTemplate 传输发送的数据格式是以 json 格式的所以要添加撒谎给你 @RequestBody
        // 将json 格式的字符串转换为 bean对象进行赋值
        // 同时,我们 bean 对象传输过程中是需要序列化的。
        log.info("member-service-provider-10000 save member={}", member);
        int affected = memberService.save(member);
        if (affected > 0) { // 说明添加成功
            return Result.success("添加会员成功 member-service-nacos-provider-10004 ", affected);
        } else {
            return Result.error("401", "添加会员失败");
        }
    }


    /**
     * 这里我们使用 url占位符 + @PathVariable
     *
     * @param id
     * @return
     */
    @GetMapping("/member/get/{id}")
    public Result getMemberById(@PathVariable("id") Long id, HttpServletRequest request) {
        Member member = memberService.queryMemberById(id);

        String color = request.getParameter("color");
        String age = request.getParameter("age");


        // 模拟超时 ,这里暂停 5秒
       /* try {
            TimeUnit.SECONDS.sleep(5);
        } catch (Exception e) {
            e.printStackTrace();
        }*/

        // 使用 Result 把查询到的结果返回
        if (member != null) {
            return Result.success("查询会员成功 member-service-nacos-provider-10004  color" + color + "age" + age, member);
        } else {
            return Result.error("402", "ID" + id + "不存在 member-service-nacos-provider-10004 ");
        }
    }

}

  1. 测试:
  1. 启动 Nacos Server 8848
  2. 启动 member-service-nacos-provider-10004
  3. 观察 nacos 服务是否注册成功

在这里插入图片描述

在这里插入图片描述

浏览器: http://localhost:10004/member/get/1

在这里插入图片描述

  1. 创建 member-service-nacos-provider-10006 并注册到 NacosServer8848

创建 member-service-nacos-provider-10006

  1.          参考member-service-nacos-provider-10004  来创建 member-service-nacos-provider-10006  即可
    
  2.          创 建 好 后 , 使 用  member-service-nacos-provider-10004   的 源 码 和 配 置 替 换 member-service-nacos-provider-10006 生成的代码
    
  3.          提醒,拷贝时不要忘记拷贝  resources/mapper/MemberMapper.xml  这些  xxx.xml  文 件
    

在该 'member-service-nacos-provider-10006' 项目 pom.xml 。导入 Naocs 依赖的 jar

在这里插入图片描述

创建 member-service-nacos-provider-10006 当中的 resources 类路径下,创建 application.yml, 同时在其中编写 Nacos 的相关配置。如下图所示:

在这里插入图片描述

server:
  port: 10006
spring:
  application:
    name: member-service-nacos-provider # 配置应用的名称
    # 配置 nacos
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 # 配置注册到哪个 Nacos Server的地址
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource # 配置 alibaba 的数据库连接池
    password: MySQL123
    username: root
    url: jdbc:mysql://localhost:3306/e_commerce_center_db?useSSL=true&useUnicode=true&characterEncoding=UTF-8

mybatis:
  mapper-locations: classpath:mapper/*.xml # 指定 mapper.xml 文件位置 classpath 表示 resources 目录下
  type-aliases-package: com.rainbowsea.springcloud.entity # 实例 bean 类所在的包,这样可以通过类名的方式



# 配置暴露所有的监控点:
management:
  endpoints:
    web:
      exposure:
        include: '*'


创建主启动类 MemberNacosProviderApplication10006:

在这里插入图片描述

修改 com/rainbowsea/springcloud/controller/MemberController.java 的输出信息。

在这里插入图片描述

package com.rainbowsea.springcloud.controller;


import com.rainbowsea.springcloud.entity.Member;
import com.rainbowsea.springcloud.entity.Result;
import com.rainbowsea.springcloud.service.MemberService;
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.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

@RestController
@Slf4j
public class MemberController {

    @Resource
    private MemberService memberService;


    /*
    说明:
         1. 我们的前端如果是以 json 格式来发送添加信息的Member,那么我们需要使用 @RequestBody
         才能将数据封装到对应的 bean,同时保证http的请求的 content-type 是对应
         2. 如果前端是以表单形式提交了,则不需要使用@RequestBody,才会进行对象bean参数封装,同时
         保证 http的请求的 content-type 是对应
     */

    /**
     * 添加方法/接口
     *
     * @param member
     * @return
     */
    @PostMapping("/member/save")
    public Result save(@RequestBody Member member) {
        // 注意:微服务组件通信的坑点:
        // 这里我们使用 RestTemplate 传输发送的数据格式是以 json 格式的所以要添加撒谎给你 @RequestBody
        // 将json 格式的字符串转换为 bean对象进行赋值
        // 同时,我们 bean 对象传输过程中是需要序列化的。
        log.info("member-service-provider-10006 save member={}", member);
        int affected = memberService.save(member);
        if (affected > 0) { // 说明添加成功
            return Result.success("添加会员成功 member-service-nacos-provider-10006 ", affected);
        } else {
            return Result.error("401", "添加会员失败");
        }
    }


    /**
     * 这里我们使用 url占位符 + @PathVariable
     *
     * @param id
     * @return
     */
    @GetMapping("/member/get/{id}")
    public Result getMemberById(@PathVariable("id") Long id, HttpServletRequest request) {
        Member member = memberService.queryMemberById(id);

        String color = request.getParameter("color");
        String age = request.getParameter("age");


        // 模拟超时 ,这里暂停 5秒
       /* try {
            TimeUnit.SECONDS.sleep(5);
        } catch (Exception e) {
            e.printStackTrace();
        }*/

        // 使用 Result 把查询到的结果返回
        if (member != null) {
            return Result.success("查询会员成功 member-service-nacos-provider-10006  color" + color + "age" + age, member);
        } else {
            return Result.error("402", "ID" + id + "不存在 member-service-nacos-provider-10006 ");
        }
    }

}

测试 保证 Nacos Server 8848 是启动的 启动 member-service-nacos-provider-10006 观察 nacos 服务是否注册成功。

在这里插入图片描述

在这里插入图片描述

浏览器: http://localhost:10006/member/get/1

在这里插入图片描述

2.2 创建 Nacos 的服务消费者

需求说明/图解:

在这里插入图片描述

创建 member-service-nacos-consumer-80 并注册到 NacosServer8848。如下图所示:

参考 member-service-consumer-80 来创建 member-service-nacos-consumer-80 即可

在这里插入图片描述

修改 member-service-nacos-consumer-80 模块当中的 pom.xml 文件,导入相关的 jar 依赖。如下图所示:在这里插入图片描述

<?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">
    <parent>
        <artifactId>e-commerce-center</artifactId>
        <groupId>com.rainbowsea</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>member-service-nacos-consumer-80</artifactId>


    <!--    引入相关的依赖:我们引入了当前所需要的依赖,后面如果有其它的需要,再灵活添加-->
    <dependencies>

        <!--引入 alibaba-nacos -discovery   -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <!--        引入 web-starter 说明:我们使用版本仲裁(从父项目继承了版本)-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--1. starter-actuator 是sprng boot 程序的监控系统,可以实现健康检查,info 信息等
         2. 访问http://localhost:10000/actuator 可以看到相关链接,还可以做相关配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>


        <!--        lombok 引入-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!--        引入 test-starter -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--        引入我们自己对 bean 封装成 api 的模块内容-->
        <dependency>
            <groupId>com.rainbowsea</groupId>
            <artifactId>e_commerce_center-common-api</artifactId>
            <version>${project.version}</version>
        </dependency>

    </dependencies>

</project>

编写 resoucse 其中的application.yaml 文件当中,编写对于 Nacos 的相关的配置信息。如下图所示:

在这里插入图片描述

server:
  port: 80
spring:
  application:
    name: member-service-nacos-consumer-80

  #配置 nacos 注册中心
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 # 配置 nacos server的地址

创建该模块的,主启动类/(场景启动器)。注意如果需要使用 Nacos ,需要在主启动类上加上了``注解,引用Nacos 的注解,启用 Nacos 的注册中心。

在这里插入图片描述

package com.rainbowsea.springcloud;


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

@SpringBootApplication
@EnableDiscoveryClient  // 表示引入 Nacos 注册中心,启动 nacos 发现注解
public class MemberNacosConsumerApplication80 {

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

创建配置类 com/rainbowsea/springcloud/config/CustomizationBean.java

特别说明:nacos 本身就集成了 Ribbon, 直接支持 Ribbon+RestTemplate 调用

在这里插入图片描述

package com.rainbowsea.springcloud.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;

/*
配置类
配置注入 RestTemplate bean /对象

 */
@Configuration
public class CustomizationBean {


    // nacos 本身就集成了 Ribbon ,直接支持 Ribbon + RestTemplate 调用
    /*
    配置注入 RestTemplate bean /对象
    这里的 @LoadBalanced 就是赋予 RestTemplate 负载均衡的能力
    默认是使用轮询算法来访问远程调用接口/地址
     */
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }

}

创建 com/rainbowsea/springcloud/controller/MemberNacosConsumerController.java

在这里插入图片描述

详细内容如下:

package com.rainbowsea.springcloud.controller;


import com.rainbowsea.springcloud.entity.Member;
import com.rainbowsea.springcloud.entity.Result;
import lombok.extern.slf4j.Slf4j;
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.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.List;

@RestController
@Slf4j
public class MemberNacosConsumerController {

    private static final String MEMBER_SERVICE_NACOS_PROVIDER_URL = "http://member-service-nacos-provider"; //
    // 后面这里地方会修改成提供服务模块的注册别名,可以在 nacos 当中查看到,对应的服务名


    // 装配 RestTemplate bean/对象
    @Resource
    private RestTemplate restTemplate;
    @Resource // 装配到 Spring ioc 容器当中
    private DiscoveryClient discoveryClient;

    @PostMapping("/member/nacos/consumer/save")
    public Result<Member> save(Member member) {

        log.info("member-service-consumer-80 save member={}", member);
        return restTemplate.postForObject
                (MEMBER_SERVICE_NACOS_PROVIDER_URL + "/member/save", member, Result.class);

    }


    // 注意:有两个是这个包下的 : org.springframework.cloud.client.discovery.DiscoveryClient

    /**
     * 方法/接口,调用服务接口,返回 member 对象信息
     *
     * @param id
     * @return
     */
    @GetMapping("/member/nacos/consumer/get/{id}")
    public Result<Member> getMemberById(@PathVariable("id") Long id) {

        // 这里就用两个参数
        // 第一个参数,因为是查询,所以这里我们直接字符串拼接上去
        // 这里通过
        return restTemplate.getForObject(MEMBER_SERVICE_NACOS_PROVIDER_URL + "/member/get/" + id, Result.class);
    }

    // 注意:想要获取到服务端信息,还需要在SpringBoot 启动场景上加上:@EnableDiscoveryClient // 启用服务发现 注解才行
    @GetMapping("/member/consumer/discovery")
    public Object discovery() {
        List<String> services = discoveryClient.getServices();

        // 遍历 services
        for (String service : services) {
            log.info("服务名==={}", service);
            // 再根据服务名获取更加详细的信息
            List<ServiceInstance> instances = discoveryClient.getInstances(service);
            for (ServiceInstance instance : instances) {
                log.info("id={},host={},uri={}", instance.getServiceId(), instance.getHost(), instance.getUri());
            }
        }


        return this.discoveryClient;
    }
}

启动 Nacos Server 8848 启动 member-service-nacos-provider-10004/10006 启动 member-service-nacos-consumer-80 浏览器: http://localhost/member/nacos/consumer/get/1

浏览器输入: http://localhost/member/nacos/consumer/get/1 注意观察是否轮询调用。

在这里插入图片描述

在这里插入图片描述

同样的,我们也可以不采用 Nacos 默认的 "轮询的负载均衡",而采用自己自定义的负载均衡的算法。

这里我们配置自己的:配置自己的负载均衡算法——> 这里我们通过配置类 的方式,配置负载均衡算法。如下:

在这里插入图片描述

package com.rainbowsea.springcloud.config;


import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/*
特别说明: Nacos 不需要额外的在场景启动器上指明该使用的“负载均衡”算法。
因为 Nacos 本身就包含了 这些,直接使用注解即可,直接使用配置类上加上注解就行
 */
@Configuration
public class RibbonRule {
    //配置注入自己的负载均衡算法
    @Bean
    public IRule myRibbonRule() {
//这里老师返回的是 RandomRule,当然小伙伴也可以自己指定
        return new RandomRule();

    }
}

运行测试:查看是否是,随机的负载均衡算法。注意:因为这里我们修改了源码,所以需要重新启动服务。

在这里插入图片描述

3. Spring Cloud Alibaba Nacos AP 和 CP 切换-理论

各种注册中心对比:

在这里插入图片描述

选择 AP 还是 CP

  1. CP: 服务可以不能用,但必须要保证数据的一致性。
  2. AP:数据可以短暂不一致,但最终是需要一致的,无论如何都要保证服务的可用
  3. 取舍:只能在 CP 和 AP 选择一个平衡点,大多数都是选择 AP模式。

Nacos 集群默认支持的是CAP原则中的AP原则,但是也可切换为CP原则(一般不切 换)

  • CURL切换命令: curl -X PUT '$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=serverMode&va lue=CP'
  • URL指令:$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP
  • 参考文档:www.jianshu.com/p/c56e22c22…

4. Spring Cloud Alibaba Nacos 配置中心实例

Nacos 不仅是注册中心 ,也是配置中心 。如下我们进行 Nacos 的配置中心进行操作。

需求分析/图解

在这里插入图片描述

在 Nacos Server 加入配置:

特别说明:不要关闭 Nacos 命令窗口,在浏览器上输入:http://localhost:8848/nacos。账号和密码都是:`nacos`

核心操作: 进入 Nacos 可视化界面,添加配置信息。如下我们添加:Data ID: e-commerce-nacos-config-client-dev.yaml 的配置。加入配置, 特别提醒: 文件后缀.yaml ,不可以是别的。

在这里插入图片描述

在这里插入图片描述

config:
 ip: "127.0.0.1"
 name: "RainbowSea"

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

创建 Nacos 配置客户端模块 e-commerce-nacos-config-client5000

在这里插入图片描述

修改 pom.xml 引入相关 jar 依赖。

在这里插入图片描述

<?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">
    <parent>
        <artifactId>e-commerce-center</artifactId>
        <groupId>com.rainbowsea</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>e-commerce-nacos-config-client5000</artifactId>


    <!--    引入相关的依赖:我们引入了当前所需要的依赖,后面如果有其它的需要,再灵活添加-->
    <dependencies>

        <!--nacos-config-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <!--引入 alibaba-nacos-discovery  即场景启动器,使用版本仲裁 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <!--        引入 web-starter 说明:我们使用版本仲裁(从父项目继承了版本)-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--1. starter-actuator 是sprng boot 程序的监控系统,可以实现健康检查,info 信息等
         2. 访问http://localhost:10000/actuator 可以看到相关链接,还可以做相关配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>


        <!--        lombok 引入-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!--        引入 test-starter -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--        引入我们自己对 bean 封装成 api 的模块内容-->
        <dependency>
            <groupId>com.rainbowsea</groupId>
            <artifactId>e_commerce_center-common-api</artifactId>
            <version>${project.version}</version>
        </dependency>

    </dependencies>

</project>

创建 application.yml。编写配置 Nacos 配置中心的信息。

在这里插入图片描述

spring:
  profiles:
    active: dev # 指定环境,常见的环境有 dev(开发)/test(测试)/prod(生产)

特别说明:

  • 开发环境(dev): 开发环境是程序员,专门用于开发的服务器,配置可以比较随意,为了开发调用方便,一般打开全部错误报告。
  • 测试环境(test): 一般是克隆一份生产环境的配置,一个程序在测试环境工作不正常,那么肯定不能把他发布到生产机器上。
  • 生产环境(prod): 是直接正是提供对外服务的,一般会关掉错误报告,打开错误日志。

三个环节也可以说是系统开发的三个阶段:开发->测试->上线,其中生产环境也就是通常说的真实环境。

在 resoures 创建 bootstrap.yml

在这里插入图片描述

server:
  port: 5000

spring:
  application:
    #    name: e-commerce-nacos-config
    name: e-commerce-nacos-config-client
  # 配置 nacos
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 # 配置服务注册中心地址
      config:
        server-addr: localhost:8848 # 配置中心地址
        file-extension: yaml # 指定yaml格式的配置,配置中心放的配置是 yaml格式的配置
        #        group: order # 指定 order组,默认DEFAULT_GROUP


        

#        group: search # 指定 seckill组,默认DEFAULT_GROUP
#        namespace: f87c69cd-9fd2-4326-b58a-9a5d326c3af1 # 指定 namespace id 百度的
#        namespace: cd4b7aa7-ae61-4d5d-9eb5-efb29a07f702 # 指定对应 namespace id 阿里的



bootstrap.yml 配置文件编写的说明:

# 解读:
# 1. nacos 配置客户端/当前的微服务模块,会根据配置,找到配置中心的数据(配置文件)
# 2. config.server-addr: localhost:8848 可以找到配置中心
# 3. spring.application.name 对应是 DataId e-commerce-nacos-config
# 4. 在 application.yaml: 配置 spring.profiles.active dev
# 5. spring.cloud.nacos.config.file-extension 配置文件的扩展名 .yaml
# 6. 小结: 根据配置就是到localhost:8848 下的 e-commerce-nacos-config-dev.yaml
# 获取配置信息/数据
# 7. 规则就是:${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
# 来定位配置中心的 Data ID

在这里插入图片描述

业务类:创建 NacosConfigClientController

在这里插入图片描述

package com.rainbowsea.springcloud.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  // 实现配置自动更新: Spring Cloud 原生注解,实现了配置数据的自动刷新
public class NacosConfigClientController {

    /*
    特别说明:
    1. client 会拉取 nacos server 的 e-commerce-nacos-config-client-dev.yaml
    - config:
        ip: "122.22.22.22"
        name: "RainbowSea"
    2. @Value("${config.ip}") 会将 config.ip 赋给 configIP
    3. 这里的@"${config.ip}" 不能乱写,要有依据,如果有一点不一致的都会,报错,无法运行的
    是在: org.springframework.beans.factory.annotation.Value 包下的
     */

    //@Value("${config:ip}")  // 使用 : 也是可以的
    @Value("${config.ip}")  // 使用 : 也是可以的
    private String configIp;

    @Value("${config.name}")
    private String configName;


    @GetMapping("/nacos/config/ip")
    public String getConfigIp() {
        return configIp;
    }

    @GetMapping("/nacos/config/name")
    public String getConfigName() {
        return configName;
    }
}

讲解说明:

使用 @Value() 注解的方式,可以获取到 Nacos 配置中心,所配置的信息。

语法:@Value("${config.ip}") 或者是 @Value("${config:ip}"),

@Value("${config.ip}"), 是 import org.springframework.beans.factory.annotation.Value 包下的内容。

同时特别注意:ip 和 你在 Nacos 当中编写配置的信息是一定必须要保持一致的。一定出现了不一致的问题,便会运行不起来。

    //@Value("${config:ip}")  // 使用 : 也是可以的
    @Value("${config.ip}")  // 使用 : 也是可以的
    private String configIp;

    @Value("${config.name}")
    private String configName;

在这里插入图片描述

更多配置信息,大家可以移步至:nacos.io/zh-cn/docs/…

在这里插入图片描述

测试: 启动 Nacos Server 启动 e-commerce-nacos-config-client5000 浏览器: http://localhost:5000/nacos/config/ip

在这里插入图片描述

浏览器输入: http://localhost:5000/nacos/config/name

在这里插入图片描述

4.1 注意事项和细节

  1. @Value("${config.ip}"), 是 import org.springframework.beans.factory.annotation.Value
  2. 配置文件 application.yml 和 bootstrap.yml 结合会得到配置文件/资源的地址
  3. 参考文档: nacos.io/zh-cn/docs/…

在这里插入图片描述

  1. 注意在 Nacos Server 的配置文件的后缀是 .yaml , 而不是 .yml
  2. 在项目初始化时,要保证先从配置中心进行配置拉取,拉取配置之后,才能保证项目的正常启动, 也就是说如果项目不能正确的获取到 Nacos Server 的配置数据,项目是启动不了的。也就是要让你@Value(xxx.xx) 要与在 Nacos Server 的配置数据要保持一致。不然,是无法获取到 Nacos 配置中心当中编写的配置信息,也就是拉取失败了。运行测试。

在这里插入图片描述

  1. @RefreshScope 是 springcloud 原 生 注 解 , 实 现 配 置 信 息 自 动 刷 新 , 如 果 在 Nacos Server 修改了配置数据,Client 端就会得到最新配置。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

5. Spring Cloud Alibaba Nacos 分类配置(实现配置隔离)

Nacos 作为一个配置中心,存储着在多个服务之间的配置信息,配置信息之间,需要相互分类,相互隔离开来。

关于 Spring Cloud Alibaba Nacos 分类配置(实现配置隔离) 有三种方案:

  1. DataID 分类配置方案
  2. Group 分类配置方案
  3. Namespace 分类配置方案

友人会说可以通过:config 这样前缀进行分类鸭。

在这里插入图片描述

可以是可以,但是存在一个致命的问题,我们知道一旦我们的服务拉取不到 Nacos 配置中心的配置信息,服务就直接宕机,无法运行了。所以一旦,我们将所以服务的配置信息都配置到一个Nacos 的 yaml 文件当中的话,一旦这个 Nacos 宕机了,那么我们整个微服务就无法使用了。

所以为了提高 我们配置中心的可用性,我们也可以配置多个 Nacos 配置中心,这样一个 Nacos 就无法宕机了,其它的 Nacos 配置依旧可以正常运行。不受影响。

5.1 DataID 分类配置方案

需求分析/图解

在这里插入图片描述

通过创建多个不同的 Data ID 进行隔离,分类配置信息。

如下:

在 nacos server 创建新的配置:

  • e-commerce-nacos-config-client-test.yaml
  • e-commerce-nacos-config-client-dev.yaml

在这里插入图片描述

在这里插入图片描述

修改 application.yml,修改为 test 。这里我们读取 e-commerce-nacos-config-client-test.yaml 的配置信息。

在这里插入图片描述

测试 浏览器: http://localhost:5000/nacos/config/name

在这里插入图片描述 浏览器输入: http://localhost:5000/nacos/config/ip

在这里插入图片描述

5.2 Group 分类配置方案

需求分析/图解

在这里插入图片描述

对于 Nacos 的配置中心的,配置分类,还可以通过 group 组进行分类。

在这里插入图片描述

首先:我们需要进入到 Nacos 服务当中,同时注意:我们对应的 Nacos 的命令窗口不可以关闭。关闭了,则是无法获取到对应上的 Nacos (配置中心)当中的配置信息的,拉取配置信息是失败的,也是无法运行启动的。

在这里插入图片描述

在 nacos server 创建新的配置:Data Id 是为:e-commerce-nacos-config-client-dev.yaml ,分组在 order 当中。

在这里插入图片描述

config:
  ip : "127.0.0.1 (order) 组当中的 IP "
  name: "RainbowSea (order) 组当中的 Name" 

在 nacos server 创建新的配置 Data Id 为 e-commerce-nacos-config-client-dev.yaml,分组在: seckill

在这里插入图片描述

config:
  ip: "127.0.0.1 (seckill) 组当中的 IP"
  name: "RainbowSea(seckill) 组当中的 Name"

在这里插入图片描述

修改 application.yml 为 dev 开发环境。如下图所示:

在这里插入图片描述

spring:
  profiles:
    active: dev # 指定环境,常见的环境有 dev(开发)/test(测试)/prod(生产)

修改 bootstrap.yml;为其增加 group 的分组的参数。如下图所示:

在这里插入图片描述

server:
  port: 5000

spring:
  application:
    #    name: e-commerce-nacos-config
    name: e-commerce-nacos-config-client
  # 配置 nacos
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 # 配置服务注册中心地址
      config:
        server-addr: localhost:8848 # 配置中心地址
        file-extension: yaml # 指定yaml格式的配置,配置中心放的配置是 yaml格式的配置
          group: order # 指定 order组,默认DEFAULT_GROUP




#        group: search # 指定 seckill组,默认DEFAULT_GROUP
#        namespace: f87c69cd-9fd2-4326-b58a-9a5d326c3af1 # 指定 namespace id 百度的
#        namespace: cd4b7aa7-ae61-4d5d-9eb5-efb29a07f702 # 指定对应 namespace id 阿里的


# 解读:
# 1. nacos 配置客户端/当前的微服务模块,会根据配置,找到配置中心的数据(配置文件)
# 2. config.server-addr: localhost:8848 可以找到配置中心
# 3. spring.application.name 对应是 DataId e-commerce-nacos-config
# 4. 在 application.yaml: 配置 spring.profiles.active dev
# 5. spring.cloud.nacos.config.file-extension 配置文件的扩展名 .yaml
# 6. 小结: 根据配置就是到localhost:8848 下的 e-commerce-nacos-config-dev.yaml
# 获取配置信息/数据
# 7. 规则就是:${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
# 来定位配置中心的 Data ID

测试: 浏览器: http://localhost:5000/nacos/config/ip

浏览器输入: http://localhost:5000/nacos/config/name

在这里插入图片描述

5.3 Namespace 分类配置方案

第三种方案,我们可以通过 Namespace 命令空间,进行一个分类配置划分,隔离。

但是其实:是 Namespace 命名空间 + group 组。两个结合起来使用,进行一个隔离,配置分类划分。

需求分析/图解

在这里插入图片描述

在 nacos server 创建新的 namespace , baidu 和 alibaba

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

同时创建 alibaba 的命名空间。如下图所示:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在 nacos server 服务UI界面当中创建,在 alibaba 的命名空间下,创建一个 一个 Data Id 为 e-commerce-nacos-config-client .yaml, group 分组为 : seckill 的配置信息。如下图,所示:

在这里插入图片描述

在这里插入图片描述

config:
  ip: "127.0.0.1 (阿里巴巴)秒杀开发小组的模块的IP "
  name: "RainbowSea(阿里巴巴)秒杀开发小组的模块的Name"

同理我们 在 nacos server 服务UI界面当中创建,在 baidu的命名空间下,创建一个 一个 Data Id 为 e-commerce-nacos-config-client .yaml, group 分组为 : search 的配置信息。如下图,所示:

在这里插入图片描述

在这里插入图片描述

修改 application.yaml 的配置信息;修改为 dev 的开发环境的信息。

在这里插入图片描述

spring:
  profiles:
    active: dev # 指定环境,常见的环境有 dev(开发)/test(测试)/prod(生产)

修改 bootstrap.yaml 的配置信息,在其中添加上,Namespace 命名空间,Group 的组的配置。如下图所示:

在这里插入图片描述

在这里插入图片描述

浏览器: http://localhost:5000/nacos/config/name 浏览器输入: http://localhost:5000/nacos/config/ip

测试:

在这里插入图片描述

我们再次修改 applicaton.yaml 和 bootstrap.yaml 的配置信息 ,获取到 baidu 所配置的信息。如下图所示:

在这里插入图片描述

重启启动服务器,因为我们修改了相关的配置信息。

浏览器: http://localhost:5000/nacos/config/name 浏览器输入: http://localhost:5000/nacos/config/ip

在这里插入图片描述

5.4 Namespace / Group / Data ID 三种分类配置方式的关系

一图胜千言

在这里插入图片描述

  1. Nacos 默认的命名空间是: public,Namespace 主要用来实现配置隔离,隔离范围大
  2. Group 默认是 DEFAULT GROUP, GROUP 可以把不同的微服务划分到同一个分组里面去
  3. Service 就是微服务,相同的 Service 可以是一个 Cluster(簇/集群),Instance 就是微服务的实例

Nacos的配置管理模型:

数据模型: Nacos 使用的核心数据模型包括 NamespaceGroupData ID ,实现了配置的逻辑隔离和分组管理。

Namespace VS Group

  • Namespace: 是用于逻辑隔离 的最高级别单位,不同的 Namespace 之间是完全隔离的。服务实例,配置等资源都不会在不同的 Namespace 之间共享。
  • Group: 是用于同一 Namespace内 的服务进行进一步分组 的单位。可以用于将同一个 namesapce 中的服务按业务分类或功能模块进行管理,例如:一个 Namespace 可以包含多个 Group ,如 paymentorderinventory 等。

Namespace VS Data ID

  • Data ID: 是 Nacos 配置管理中的概念,表示具体的配置信息项。每个配置项通过 Data ID 来标识,用于管理具体的配置内容。
  • Namespace: 则是用来将多个 Data ID 进行隔离管理的,不同的 Namespace 可以有相同的 Data ID ,但它们所代表的配置信息是独立的。

特别说明:

Nacos 客户端维护一个本地缓存,客户端接受到配置更新后,会自动刷新本地缓存的配置,当与Nacos服务器的连接出现异常或服务器不可用时,可以从本地缓存中读取配置 ,保证系统的基本运行不受影响。这个缓存机制也有助于减少服务器压力,提高系统的可用性。 所以当面试官问你 Nacos 配置中心挂了实例会不会立马收到影响呢,答案是:不会的,因为存在本地缓存的机制。

6. 总结:

  1. 一句话:Nacos 就是注册中心[替代 Eureka] + 配置中心[替代 Config] ,简单的说:Nacos 和 Eureka 是一样的
  2. 特别说明:必须在主启动(场景启动器)类上加上@EnableDiscoveryClient 注解(引用Nacos发现注解),才能启动使用上 Nacos 注册中心
  3. Nacos 不仅是注册中心 ,也是配置中心 。如下我们进行 Nacos 的配置中心进行操作。
  4. 关于 Spring Cloud Alibaba Nacos 分类配置(实现配置隔离) 有三种方案:
    1. DataID 分类配置方案
    2. Group 分类配置方案
    3. Namespace 分类配置方案
  5. 特别注意:设置配置当中的注意事项和细节
  6. Namespace / Group / Data ID 三种分类配置的关系。

7. 最后:

“在这个最后的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。”

在这里插入图片描述