• 『Nacos』 入门教程


    前言

    本文为 Nacos 平台快速入门教程,本文将会使用通俗易懂的语言手把手带您了解、使用 Nacos 平台,适合未接触过 Nacos 的初学者

    官方手册:Nacos | Nacos

    官方仓库:alibaba/nacos

    版本:2.X

    本文示例代码仓库:ReturnTmp/nacos-demo (github.com)

    Nacos | Nacos

    介绍

    Nacos 阿里巴巴推出来的开源项目,是更易于构建云原生应用动态服务发现、配置管理和服务管理平台

    Nacos 致力于发现、配置和管理微服务,并提供简单易用的特性集,能够快速实现动态服务发现、服务配置、服务元数据及流量管理。

    Nacos 更敏捷和容易地构建、交付和管理微服务平台,构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施

    下面将会对比常用注册中心和配置中心,并且向您介绍注册中心和配置中心的概念

    注:如果您只想要快速开始,可以直接跳转到 快速开始 章节,跳过下面繁琐的概念

    注册中心

    常见注册中心组件

    注册中心主要分为三种角色:

    • 服务提供者(RPC Server):在启动时,向 Registry 注册自身服务,并向 Registry 定期发送心跳汇报存活状态。
    • 服务消费者(RPC Client):在启动时,向 Registry 订阅服务,把 Registry 返回的服务节点列表缓存在本地内存中,并与 RPC Sever 建立连接。
    • 服务注册中心(Registry):用于保存 RPC Server 的注册信息,当 RPC Server 节点发生变更时,Registry 会同步变更,RPC Client 感知后会刷新本地 内存中缓存的服务节点列表。

    最后,RPC Client 从本地缓存的服务节点列表中,基于负载均衡算法选择一台 RPC Sever 发起调用。

    常用注册中心:Eureka,Zookeeper(不推荐),Nacos,Consul,ETCD

    配置中心

    为什么使用配置中心

    • 配置实时生效:传统的静态配置方式要想修改某个配置只能修改之后重新发布应用,要实现动态性,可以选择使用数据库,通过定时轮询访问数据库来感知配置的变化。轮询频率低感知配置变化的延时就长,轮询频率高,感知配置变化的延时就短,但比较损耗性能,需要在实时性和性能之间做折中。配置中心专门针对这个业务场景,兼顾实时性和一致性来管理动态配置
    • 配置管理流程:配置的权限管控、灰度发布、版本管理、格式检验和安全配置等一系列的配置管理相关的特性,也是配置中心不可获取的一部分;
    • 分布式场景:随着采用分布式的开发模式,项目之间的相互引用随着服务的不断增多,相互之间的调用复杂度成指数升高,每次投产或者上线新的项目时苦不堪言,需要引用配置中心治理

    配置中心支持功能

    • 灰度发布:配置的灰度发布是配置中心比较重要的功能,当配置的变更影响比较大的时候,需要先在部分应用实例中验证配置的变更是否符合预期,然后再推送到所有应用实例。
    • 权限管理:配置的变更和代码变更都是对应用运行逻辑的改变,重要的配置变更常常会带来核弹的效果,对于配置变更的权限管控和审计能力同样是配置中心重要的功能。
    • 版本管理&回滚:当配置变更不符合预期的时候,需要根据配置的发布版本进行回滚。
    • 配置格式校验:应用的配置数据存储在配置中心一般都会以一种配置格式存储,比如Properties、Json、Yaml等,如果配置格式错误,会导致客户端解析配置失败引起生产故障,配置中心对配置的格式校验能够有效防止人为错误操作的发生,是配置中心核心功能中的刚需。
    • 监听查询:当排查问题或者进行统计的时候,需要知道一个配置被哪些应用实例使用到,以及一个实例使用到了哪些配置。
    • 多环境:在实际生产中,配置中心常常需要涉及多环境或者多集群,业务在开发的时候可以将开发环境和生产环境分开,或者根据不同的业务线存在多个生产环境。如果各个环境之间的相互影响比较小(开发环境影响到生产环境稳定性),配置中心可以通过逻辑隔离的方式支持多环境。
    • 多集群:当对稳定性要求比较高,不允许各个环境相互影响的时候,需要将多个环境通过多集群的方式进行物理隔离。

    理论上来说,只要能作为分布式存储的服务都作为配置中心,比如说 Zookeeper 和 ETCD,但是由于这两个工具没有方便的UI管理工具,且缺乏权限、审核、灰度发布、审核机制等,且通常定义为服务注册中心,因此不优先考虑

    常用配置中心主要有:Disconf、Spring Cloud Config、Apollo 和 Nacos

    快速开始

    官方对应文档:Nacos 快速开始 | Nacos

    安装

    本次博主将会使用 Windows 系统进行演示,Linux 系统用户可以直接参考 Windows 安装流程

    注:您的机器配置至少需要 2C4G 60G

    因为 Nacos 依赖 Java 环境来运行。如果您是从代码开始构建并运行 Nacos,还需要为此配置 Maven环境,请确保是在以下版本环境中安装使用

    1. 64 bit OS,支持 Linux/Unix/Mac/Windows
    2. 64 bit JDK 1.8+;下载 & 配置
    3. Maven 3.2.x+;下载 & 配置

    下载

    我们可以通过源码和发行包两种方式来获取 Nacos,本次将会使用源码的形式获取安装包

    git clone https://github.com/alibaba/nacos.git
    cd nacos/
    mvn -Prelease-nacos -Dmaven.test.skip=true clean install -U  
    # Windows
    dir distribution/target/
    # Linux
    ls -al distribution/target/
    
    # 改变 $version 为真实名称
    cd distribution/target/nacos-server-$version/nacos/bin
    # 博主实际命令
    cd distribution/target/nacos-server-2.3.0-BETA/nacos/bin
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    命令执行可能出现如下问题

    上面的 mvn -Prelease-nacos -Dmaven.test.skip=true clean install -U 命令,在 CMD 命令行环境是没问题的,但是在 PowerShell 会出现 Unknown lifecycle phase ".test.skip=true". 问题

    PowerShell 中应该替换为如下命令

    mvn -Prelease-nacos '-Dmaven.test.skip=true' clean install -U  
    
    • 1

    配置

    注:在2.2.0.1和2.2.1版本时,必须执行此变更,否则无法启动;其他版本为建议设置

    修改conf目录下的application.properties文件。

    设置其中的nacos.core.auth.plugin.nacos.token.secret.key值,详情可查看鉴权-自定义密钥.

    注意,文档中的默认值SecretKey012345678901234567890123456789012345678901234567890123456789VGhpc0lzTXlDdXN0b21TZWNyZXRLZXkwMTIzNDU2Nzg=为公开默认值,可用于临时测试,实际使用时请务必更换为自定义的其他有效值。

    启动

    本次演示将会使用单机模式 / 非集群模式运行 Nacos

    Windows

    startup.cmd -m standalone
    
    • 1

    Linux/Unix/Mac

    sh startup.sh -m standalone
    
    • 1

    如果您是 ubuntu 系统或运行脚本报错提示,请执行如下脚本

    bash startup.sh -m standalone
    
    • 1

    关闭

    # Windows
    shutdown.cmd
    # Linux/Unix/Mac
    sh shutdown.sh
    
    • 1
    • 2
    • 3
    • 4

    服务注册&发现和配置管理

    服务注册
    curl -X POST 'http://127.0.0.1:8848/nacos/v1/ns/instance?serviceName=nacos.naming.serviceName&ip=20.18.7.10&port=8080'
    
    • 1
    服务发现
    curl -X GET 'http://127.0.0.1:8848/nacos/v1/ns/instance/list?serviceName=nacos.naming.serviceName'
    
    • 1
    发布配置
    curl -X POST "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test&content=HelloWorld"
    
    • 1
    获取配置
    curl -X GET "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test"
    
    • 1

    访问

    启动服务之后我们可以访问地址:http://127.0.0.1:8848/nacos

    用户名 / 密码:nacos/nacos

    注:我这里没有鉴权,所以直接跳过登录,建议大家配置鉴权

    image-20231109164730548

    实战

    下面我们将会以分布式项目的形式,手把手带您了解 Nacos 在微服务架构中的实际应用

    创建父项目

    微服务中的分布式项目都会分为多个模块,构成父工程子工程的关系

    我们需要使用 IDEA 创建父项目 nacos-demo

    image-20231109192132993

    创建之后可以删除文件夹 src 毕竟对于父工程基本不需要,然后我们看父工程的 pom.xml(重点看注释)

    初始创建的 pom.xml

    
    <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.0modelVersion>
    
        <groupId>org.examplegroupId>
        <artifactId>nacos-demoartifactId>
        <version>1.0-SNAPSHOTversion>
    
        <properties>
            <maven.compiler.source>8maven.compiler.source>
            <maven.compiler.target>8maven.compiler.target>
            <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
        properties>
    
    project>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    注:上面 中 SNAPSHOT 指的的快照版本,代表当前开发版本,区别于不同版本的就是 Maven 构建的时候都会优先查看远程是否修改,然后决定拉取,而正式版本哪怕远程已经修改,也会直接使用本地版本,而不会从远程拉取

    修改之后的 pom.xml

    
    <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.0modelVersion>
    
        <groupId>org.examplegroupId>
        <artifactId>nacos-demoartifactId>
        <version>1.0-SNAPSHOTversion>
        
        <packaging>pompackaging>
    
        
        <modules>
            <module>nacos-providermodule>
        modules>
    
        <properties>
            <maven.compiler.source>8maven.compiler.source>
            <maven.compiler.target>8maven.compiler.target>
            <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
            <lombok.version>1.16.18lombok.version>
        properties>
    
        
        <dependencyManagement>
            <dependencies>
                
                <dependency>
                    <groupId>org.springframework.bootgroupId>
                    <artifactId>spring-boot-dependenciesartifactId>
                    <version>2.2.2.RELEASEversion>
                    <type>pomtype>
                    <scope>importscope>
                dependency>
                
                <dependency>
                    <groupId>org.springframework.cloudgroupId>
                    <artifactId>spring-cloud-dependenciesartifactId>
                    <version>Hoxton.SR1version>
                    <type>pomtype>
                    <scope>importscope>
                dependency>
                
                <dependency>
                    <groupId>com.alibaba.cloudgroupId>
                    <artifactId>spring-cloud-alibaba-dependenciesartifactId>
                    <version>2.1.0.RELEASEversion>
                    <type>pomtype>
                    <scope>importscope>
                dependency>
                <dependency>
                    <groupId>org.projectlombokgroupId>
                    <artifactId>lombokartifactId>
                    <version>${lombok.version}version>
                    <optional>trueoptional>
                dependency>
            dependencies>
        dependencyManagement>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.bootgroupId>
                    <artifactId>spring-boot-maven-pluginartifactId>
                    <version>2.2.6.RELEASEversion>
                    <configuration>
                        <fork>truefork>
                        <addResources>trueaddResources>
                    configuration>
                plugin>
            plugins>
        build>
    
    project>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76

    修改完之后重新构建 Maven 即可

    这里面的 dependencyManagement 是管理版本的标签,该标签可以让子项目中引用依赖而不用显式的列出版本号,但是 dependencyManagement 本身只是管理依赖,不会导入依赖,子项目中如果需要导入依赖,必须显式导入依赖,不会发生所谓的继承依赖

    Maven 依赖搜索会沿着父子层次向上走,直到找到拥有 dependencyManagement 标签的项目,然后就会使用该 dependencyManagement 元素中指定的版本号

    这样做的好处是子项目引用相同依赖,避免子项目重复声明版本,同时便于版本升级(因为只需要在顶层父容器中更新)

    创建子模块

    然后需要创建 nacos-providernacos-consumer 两个子模块,首先创建 nacos-provider

    我们需要在父项目右键创建 Moduel ,如下图

    image-20231109214848505

    image-20231109214737620

    注:如果您想要删除模块的话,直接删除文件,后面可能会遇到诸如“模块已经存在” “找不到模块”。您需要做的是在 .idea 文件夹下的 compiler.xml 对应 moudule 删除,或者更加简单的是,删除 .idea 文件夹,重启 IDEA

    然后我们做如下修改,使得父项目指定子模块,子模块引用父项目,当然还有其他修改,这里不赘述,请直接查看源码

    image-20231109220934555

    如果是子项目之间互相引用,比如说 nacos-provider 模块引用 nacos-consumer 模块,我们可以指定如下代码即可

    <dependency>
            <groupId>org.examplegroupId>
            <artifactId>nacos-consumerartifactId>
            <version>1.0-SNAPSHOTversion>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    nacos-consumer 模块大体类似,这里不再赘述

    更多代码修改比较繁琐,大家可以直接看文章开头源码即可

    Nacos 融合 Spring Boot

    启动配置管理

    官方对应文档:Nacos 融合 Spring Boot,成为注册配置中心 | Nacos

    本章节最后会通过 Nacos Server 和 nacos-config-spring-boot-starter 实现配置的动态变更

    首先我们在父项目中添加对应依赖管理,然后再分别在两个子模块中导入依赖

    父项目 pom.xml

        <properties>
            <nacos.config.spring.boot.starter.version>0.2.2nacos.config.spring.boot.starter.version>
        properties>
    
    • 1
    • 2
    • 3
                <dependency>
                    <groupId>com.alibaba.bootgroupId>
                    <artifactId>nacos-config-spring-boot-starterartifactId>
                    <version>${nacos.config.spring.boot.starter.version}version>
                dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    注意:版本 0.2.x.RELEASE 对应的是 Spring Boot 2.x 版本,版本 0.1.x.RELEASE 对应的是 Spring Boot 1.x 版本

    子项目的 application.yml 分别配置如下

    server:
      port: 8081
    
    spring:
      application:
        name: nacos-consumer
    
    nacos:
      config:
        server-addr: 127.0.0.1:8848
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    server:
      port: 8081
    
    spring:
      application:
        name: nacos-consumer
    
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    我们以 nacos-provider 为例,配置如下

    使用 @NacosPropertySource 加载 dataIdexample 的配置源,并开启自动更新

    @SpringBootApplication
    @NacosPropertySource(dataId = "example", autoRefreshed = true)
    public class NacosProviderApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(NacosProviderApplication.class, args);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    通过 Nacos 的 @NacosValue 注解设置属性值

    @Controller
    @RequestMapping("config")
    public class ConfigController {
    
        @NacosValue(value = "${useLocalCache:false}", autoRefreshed = true)
        private boolean useLocalCache;
    
        @GetMapping(value = "/get")
        @ResponseBody
        public boolean get() {
            return useLocalCache;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    Nacos 2.X 版本兼容 Nacos1.X 版本的OpenAPI, 请参考文档Nacos1.X OpenAPI使用

    下面使用的是 v1 的 API 文档

    我们启动子项目nacos-provider 之后,调用 curl http://localhost:8082/config/get,返回内容是 false

    通过调用 Nacos Open API 向 Nacos server 发布配置:dataId 为example,内容为useLocalCache=true

    curl -X POST "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=example&group=DEFAULT_GROUP&content=useLocalCache=true"
    
    • 1

    image-20231110104259805

    再次访问 http://localhost:8082/config/get,此时返回内容为true,说明程序中的useLocalCache值已经被动态更新了。

    这里说个笑话,我不小心给 clash 开了全局代理,然后我忘了,之后 Nacos 控制台就打不开了,然后用各种方法都不行,最后想起来开了全局代理

    这里的命名空间容易出现问题(主要针对 v2),贴出对应官方 issue

    issue:Nacos 2.2.0-配置中心 openAPI v2 无法创建与删除配置 · Issue #9783 · alibaba/nacos (github.com)

    启动服务发现

    该章节我们以 nacos-consumer 为例

    同样是按照上面的步骤向父子项目中添加依赖(父项目添加依赖管理,子项目导入依赖)

        <properties>
            <nacos.config.spring.boot.starter.version>0.2.2nacos.config.spring.boot.starter.version>
        properties>
    
    • 1
    • 2
    • 3
                <dependency>
                    <groupId>com.alibaba.bootgroupId>
                    <artifactId>nacos-discovery-spring-boot-starterartifactId>
                    <version>${nacos.config.spring.boot.starter.version}version>
                dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    然后配置对应的 application.yml(上面已经配置)

    使用 @NacosInjected 注入 Nacos 的 NamingService 实例

    @Controller
    @RequestMapping("discovery")
    public class DiscoveryController {
    
        @NacosInjected
        private NamingService namingService;
    
        @GetMapping(value = "/get")
        @ResponseBody
        public List<Instance> get(@RequestParam String serviceName) throws NacosException {
            return namingService.getAllInstances(serviceName);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    启动应用之后,调用 curl http://localhost:8081/discovery/get?serviceName=example,此时返回为空 JSON 数组[]

    通过调用 Nacos Open API 向 Nacos server 注册一个名称为 example 服务(成功返回 ok)

    curl -X POST "http://127.0.0.1:8848/nacos/v1/ns/instance?serviceName=example&ip=127.0.0.1&port=8081"
    
    • 1

    image-20231110112738009

    然后再次访问 curl http://localhost:8081/discovery/get?serviceName=example,此时返回内容为

    [
        {
            "instanceId": "127.0.0.1#8081#DEFAULT#DEFAULT_GROUP@@example",
            "ip": "127.0.0.1",
            "port": 8081,
            "weight": 1,
            "healthy": true,
            "enabled": true,
            "ephemeral": true,
            "clusterName": "DEFAULT",
            "serviceName": "DEFAULT_GROUP@@example",
            "metadata": {},
            "ipDeleteTimeout": 30000,
            "instanceHeartBeatTimeOut": 15000,
            "instanceHeartBeatInterval": 5000
        }
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    参考链接

    本文由博客一文多发平台 OpenWrite 发布!

  • 相关阅读:
    一个人就是一本书
    笔记本键盘失灵的修复方法
    sklearn实现多项式线性回归_一元/多元 【Python机器学习系列(八)】
    (附源码)ssm基于jsp的在线点餐系统 毕业设计 111016
    SpringBoot 刷新上下文7--执行BeanFactoryPostProcessor
    第3章 数据结构中树的概念
    如何轻松学习Java
    扩散模型又杀疯了!这一次被攻占的领域是...
    汇编精讲02
    18.1 new、delete进一步认识
  • 原文地址:https://blog.csdn.net/m0_63748493/article/details/134330549