Nacos实例一则及其源码环境搭建

Nacos实例一则及其源码环境搭建

[[N_什么是微服务]]
官页 - https://nacos.io/
Nacos Server 发布历史 - https://nacos.io/download/release-history/?spm=5238cd80.6a33be36.0.0.63db1e5d6g4YuH
Quick Start - https://nacos.io/docs/v3.0/quickstart/quick-start/?spm=5238cd80.246ac1ea.0.0.276ee755uXcz1x
文档 - https://nacos.io/docs/v2.5/overview/?spm=5238cd80.246ac1ea.0.0.276ee755uXcz1x
https://spring-cloud-alibaba-group.github.io/github-pages/greenwich/spring-cloud-alibaba.html#_introduction

Quick Start

环境

Nacos 依赖 Java 环境来运行,请确保是在以下版本环境中安装使用:

  1. 64 bit OS,支持 Linux/Unix/Mac/Windows,推荐选用 Linux/Unix/Mac。
  2. 64 bit JDK 1.8+;下载 & 配置

下载解压

进入Nacos Github 的 最新稳定版本 ,选择需要下载的Nacos版本,在Assets中点击下载 nacos-server-$version.zip 包。

unzip nacos-server-$version.zip
cd nacos/bin

启动服务器

启动命令 (standalone代表着单机模式运行,非集群模式):

# linux
sh startup.sh -m standalone

# windowns
startup -m standalone

Running in stand alone mode, All function modules
Port: 8848
Console: http://192.168.20.130:8848/nacos/index.html

打开任意浏览器,输入地址:http://192.168.20.130:8848/nacos/index.html, 即可进入Nacos控制台页面。

首次打开会要求初始化管理员用户nacos的密码。

Spring Cloud Alibaba 和 spring cloud 版本依赖关系

https://sca.aliyun.com/docs/2021/overview/what-is-sca/?spm=7145af80.493a8c99.0.0.6ec42d5bW6AfSI

Spring Cloud Alibaba Version Spring Cloud Version Spring Boot Version
2021.0.6.0* Spring Cloud 2021.0.5 2.6.13
2021.0.5.0 Spring Cloud 2021.0.5 2.6.13
2021.0.4.0 Spring Cloud 2021.0.4 2.6.11
2021.0.1.0 Spring Cloud 2021.0.1 2.6.3
2021.1 Spring Cloud 2020.0.1 2.4.2

每个 Spring Cloud Alibaba 版本及其自身所适配的各组件对应版本如下表所示:

Spring Cloud Alibaba Version Sentinel Version Nacos Version RocketMQ Version Dubbo Version Seata Version
2021.0.6.0 1.8.6 2.2.0 4.9.4 ~ 1.6.1
2021.0.5.0 1.8.6 2.2.0 4.9.4 ~ 1.6.1
2021.0.4.0 1.8.5 2.0.4 4.9.4 ~ 1.5.2
2021.0.1.0 1.8.3 1.4.2 4.9.2 ~ 1.4.2
2021.1 or 2.2.5.RELEASE or 2.1.4.RELEASE or 2.0.4.RELEASE 1.8.0 1.4.1 4.4.0 2.7.8 1.3.0

做注册中心

服务提供者

​服务发现是微服务架构中的关键组件之一。在这样的架构中,手动为每个客户端配置服务列表可能是一项艰巨的任务,并且使得动态扩展极其困难。Nacos Discovery 帮助您自动将您的服务注册到 Nacos 服务器,Nacos 服务器会跟踪服务并动态刷新服务列表。此外,Nacos Discovery 将服务实例的一些元数据,如主机、端口、健康检查 URL、主页等注册到 Nacos。

项目依赖

​父项目pom文件

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.yang</groupId>
    <artifactId>SpringCloudAlibaba</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>SpringCloudAlibaba</name>
    <packaging>pom</packaging>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud-alibaba-version>2021.0.1.0</spring-cloud-alibaba-version>
        <spring-cloud.version>2021.0.1</spring-cloud.version>
        <spring-boot.version>2.6.3</spring-boot.version>
    </properties>

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

    <modules>

        <module>nacos-service</module>
    </modules>

</project>

子模块pom文件

<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.yang</groupId>
        <artifactId>SpringCloudAlibaba</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <artifactId>nacos-service</artifactId>
    <name>nacos-service</name>
    <url>http://maven.apache.org</url>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring-boot.version}</version>
        </dependency>
<!--   nacos-discovery      -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
    </dependencies>

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

</project>


YML配置

server:
  port: 9001
spring:
  application:
    name: nacos-provider
  cloud:
    discovery:
      server-addr: 192.168.35.1:8848

management:
  endpoint:
    web:
      exposure:
        include:'*'

启动类

注意在启动类中添加@EnableDiscoveryClient注解


package org.yang.nacos.service;  
  
import org.slf4j.Logger;  
import org.slf4j.LoggerFactory;  
import org.springframework.boot.SpringApplication;  
import org.springframework.boot.autoconfigure.SpringBootApplication;  
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;  
  
/**  
 **/@SpringBootApplication  
@EnableDiscoveryClient//加此注解  
public class CloudalibabaNacosApplication {  
  
    public static void main(String[] args) {  
        SpringApplication.run(CloudalibabaNacosApplication.class, args);  
    }  
  
}

package org.yang.nacos.service.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DemoController {

    @Value("${server.port}")
    private String serverPort;

    @GetMapping(value = "/hi")
    public String getServerPort(){
        return "Hello this from nacos : "+serverPort;
    }

}

注意 服务提供者可以多个,访问路径是配置在 spring.application.name 中的名字 http://nacos-provider

服务消费者

依赖

<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.yang</groupId>
        <artifactId>SpringCloudAlibaba</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <artifactId>nacos-consumer</artifactId>
    <packaging>jar</packaging>

    <name>nacos-consumer</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>


    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring-boot.version}</version>
        </dependency>
        <!--   nacos-discovery      -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- SpringCloudAlibaba2021版本中移除了`Ribbon`,因为`Ribbon`已经停止更新维护了。使用`loadBalancer`作用新的负载均衡器。   -->  
        <dependency>  
            <groupId>org.springframework.cloud</groupId>  
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>  
        </dependency>
    </dependencies>
    

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

</project>

SpringCloudAlibaba2021版本中移除了Ribbon,因为Ribbon已经停止更新维护了。使用loadBalancer作用新的负载均衡器。

RestTemplate

restTemplate.getForObject(arg1,arg2,arg3...);

第一个参数url表示被调用的目标Rest接口位置:

  1. url的第一部分是在Nacos中注册的服务提供者名称,如果多个服务提供者注册相同名称,Ribbon会自动 负载均衡 寻找其中一个服务提供者,并且调用接口方法。
  2. url后半部是控制器的请求路径。
    第二个参数是返回值类型 :JavaBean类型或者JavaBean数组类型,如果控制器返回的是List集合,需要使用数组类型接收。
    第三个参数是可变参数 : 是传递给url的动态参数,使用参数时候需要在url上需要使用{1}、{2}、{3}进行参数占位,这样传递的参数就会自动替换占位符。

YML配置

server:  
  port: 8001  
spring:  
  application:  
    name: nacos-provider  
  cloud:  
    discovery:  
      server-addr: 192.168.35.1:8848  
# 消费者将要去访问的微服务名称(注册成功的Nacos的微服务提供者)  
service-url:  
  nacos-user-service: http://nacos-provider

调用代码

package org.yang.nacos.consumer;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableDiscoveryClient//加此注解
public class CloudalibabaNacosApplication {

    public static void main(String[] args) {
        SpringApplication.run(CloudalibabaNacosApplication.class, args);
    }
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

}

package org.yang.nacos.consumer.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;

@RestController
public class DemoController {

    @Resource
    private RestTemplate restTemplate;

    /**
     * 消费者去访问具体服务,这种写法可以实现
     * 配置文件和代码的分离
     */
    @Value("${service-url.nacos-user-service}")
    private String serverURL;

    @GetMapping(value = "consumer/nacos")
    public String getDiscovery(){
        System.err.println(serverURL);
        return restTemplate.getForObject(serverURL+"/hi",String.class);
    }
}

访问: http://localhost:8001/consumer/nacos 即实现路径是, 客户端 > nacos > 服务提供者

做配置中心

https://spring-cloud-alibaba-group.github.io/github-pages/greenwich/spring-cloud-alibaba.html#_spring_cloud_alibaba_nacos_config

业务端配置

依赖

<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.yang</groupId>
        <artifactId>SpringCloudAlibaba</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <artifactId>nacos-config</artifactId>
    <packaging>jar</packaging>

    <name>nacos-config</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring-boot.version}</version>
        </dependency>
        <!--   nacos-discovery      -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

<!--        配置 -->
        <dependency>
            <groupId> com.alibaba.cloud </groupId>
            <artifactId> spring-cloud-starter-alibaba-nacos-config </artifactId>
        </dependency>
        <!-- SpringBoot2.4之后要让 bootstrap.yaml 文件生效我们需要添加该依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>
    </dependencies>

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

配置文件

bootstrap.yml

# nacos配置
server:
  port: 3377

spring:
  application:
    name: nacos-config-client # 微服务名称
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #Nacos服务注册中心地址
      config:
        server-addr: localhost:8848 #Nacos作为配置中心地址
        file-extension: yaml #指定yaml格式的配置

注意: bootstrap.yml(或 bootstrap.properties)是Spring Cloud 微服务架构优先级最高的配置文件,仅用于系统级、高优先级的初始化配置,和普通的 application.yml 有明确分工

application.yml 配置

spring:  
  profiles:  
    active: prod # 指定相关的环境

bootstrap.yaml 配置

server:
  port: 7001
spring:
  application:
    name: nacos-config-client
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.35.1:8848 #Nacos服务注册中心地址
      config:
        server-addr: 192.168.35.1:8848 #Nacos作为配置中心地址
        file-extension: yaml #指定yaml格式的配置
        # group: XXX # 指定不同的组
        # namespace: XXX # 指定对应的命令空间

config:
  info: 默认值xxxx

业务端代码

​ 这里的@RefreshScope实现配置自动更新,意思为如果想要使配置文件中的配置修改后不用重启项目即生效,可以使用@RefreshScope配置来实现


@RestController
@RefreshScope // 自动刷新 配置中心
public class ConfigController {

    @Value("${config.info}")
    private String configInfo;

    @GetMapping("/config/hello")
    public String hello(){
        return configInfo;
    }
}

Nacos配置

dataId

在 Nacos 配置中心里,dataId 是定位配置文件的唯一标识,Spring Cloud 集成 Nacos 时,它有固定的标准格式

${prefix}-${spring.profiles.active}.${file-extension}
  1. prefix 默认为 spring.application.name 的值,也可以通过配置项 spring.cloud.nacos.config.prefix来配置。
  2. spring.profiles.active 即为当前环境对应的 profile,注意:spring.profiles.active 为空时,对应的连接符 - 也将不存在,dataId 的拼接格式变成 ${prefix}.${file-extension}(不能删除)
  3. file-exetension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置。目前只支持 propertiesyaml 类型。
  4. 通过 Spring Cloud 原生注解 @RefreshScope 实现配置自动更新:
  5. 所以根据官方给出的规则我们最终需要在Nacos配置中心添加的配置文件的名字规则和名字为:
# ${spring.application.name}-${spring.profiles.active}.${file-extension}
# 微服务名称-当前环境-文件格式
# 即# nacos-config-client-prod.yaml

增加配置

按如上格式 Data ID 是: nacos-config-client-prod.yaml
配置格式: YAML
配置内容:

config:
    info: nacos config center,10001

增加后 访问业务端 即可看到 从配置中心获取的参数: http://localhost:7001/config/info

关于命名空间、分组、环境

命名空间/分组/环境这三个是逻辑概念, 类似文件夹一样 定位到唯一的配置文件
设计出来有一些考量:

  1. Namespace : 不同环境的配置的区分隔离,例如 开发测试环境和生产环境的资源
  2. Group: 对配置集进行分组,从而区分 Data ID 相同的配置集,比如不同地区的集群划分到同一个配置组里面去
  3. Data ID: 配置集,最小的操作单位,可以简单理解为配置文件

命名空间(Namespace)
​ 用于进行租户粒度的配置隔离。不同的命名空间下,可以存在相同的 Group 或 Data ID 的配置。Namespace 的常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。

配置分组(Group)
​ Nacos 中的一组配置集,是组织配置的维度之一。通过一个有意义的字符串(如 Buy 或 Trade )对配置集进行分组,从而区分 Data ID 相同的配置集。当您在 Nacos 上创建一个配置时,如果未填写配置分组的名称,则配置分组的名称默认采用 DEFAULT_GROUP 。配置分组的常见场景:不同的应用或组件使用了相同的配置类型,如 database_url 配置和 MQ_topic 配置。

配置集 ID(Data ID)
​ Nacos 中的某个配置集的 ID。。一个系统或者应用可以包含多个配置集,每个配置集都可以被一个有意义的名称标识。Data ID 通常采用类 Java 包(如 com.taobao.tc.refund.log.level)的命名规则保证全局唯一性。此命名规则非强制。

​ 配置集:一组相关或者不相关的配置项的集合称为配置集。在系统中,一个配置文件通常就是一个配置集,包含了系统各个方面的配置。例如,一个配置集可能包含了数据源、线程池、日志级别等配置项。

源码环境

Git 仓库页 - https://github.com/alibaba/nacos

源码下载页

https://github.com/alibaba/nacos/releases/tag/2.2.3

简单分析各个模块

Nacos 本质是是一个 Spring boot 的 应用, 其主入口模块是 console 模块

<!-- Submodule management -->  
<modules>  
    <!-- 配置管理模块 -->  
    <module>config</module>  
    <!-- 核心基础模块:提供集群管理、网络通信(gRPC)、事件总线等基础设施 -->  
    <module>core</module>  
    <!-- 服务注册与发现模块:负责服务的注册、注销、健康检查及服务查询 -->  
    <module>naming</module>  
    <!-- 地址服务模块:提供 Server 节点列表查询,辅助客户端寻址 -->  
    <module>address</module>  
    <!-- 测试模块:包含项目的单元测试和集成测试代码 -->  
    <module>test</module>  
    <!-- API 定义模块:定义 ConfigService 和 NamingService 等核心接口,不含实现 -->  
    <module>api</module>  
    <!-- 客户端 SDK 模块:实现 API 接口,封装与服务端通信、缓存、心跳等逻辑 -->  
    <module>client</module>  
    <!-- 示例模块:包含使用 Nacos API 的简单代码示例 -->  
    <module>example</module>  
    <!-- 公共工具模块:包含通用的工具类、常量、异常定义,被其他模块依赖 -->  
    <module>common</module>  
    <!-- 分发打包模块:定义最终发布产物的结构,负责生成发行包 -->  
    <module>distribution</module>  
    <!-- 控制台模块:提供 Web 管理界面,用于服务管理和配置发布 -->  
    <module>console</module>  
    <!-- CMDB 模块:对接外部配置管理数据库,获取应用与主机元数据 -->  
    <module>cmdb</module>  
    <!-- Istio 适配模块:实现与 Istio 服务网格的集成(作为注册中心) -->  
    <module>istio</module>  
    <!-- 一致性协议模块:封装 CP(Raft) 和 AP(Distro) 协议,处理数据一致性 -->  
    <module>consistency</module>  
    <!-- 认证授权模块:实现用户登录、身份验证及基于角色的权限控制(RBAC) -->  
    <module>auth</module>  
    <!-- 系统管理模块:负责系统参数配置、环境变量加载及系统生命周期管理 -->  
    <module>sys</module>  
    <!-- 插件定义模块:定义 SPI 扩展点(如认证、数据源插件接口) -->  
    <module>plugin</module>  
    <!-- 插件默认实现模块:提供插件接口的默认实现逻辑 -->  
    <module>plugin-default-impl</module>  
    <!-- Prometheus 模块:暴露监控指标,支持与 Prometheus 监控系统集成 -->  
    <module>prometheus</module>  
</modules>

源码运行的踩坑指南

java: 找不到符号

...
java: 找不到符号
  符号:   类 Logger
  位置: 类 com.alibaba.nacos.plugin.trace.NacosTracePluginManager

执行一次 Maven 的 compile 即可

unnamed module

at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:184)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:162)
	... 8 common frames omitted
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make field static final boolean java.io.FileSystem.useCanonCaches accessible: module java.base does not "opens java.io" to unnamed module @26aa12dd
	at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)

JDK9之后的多模块 反射访问的问题, 对新版本的JDK支持不太好, 用JDK8 跑吧

UnknownHostException: jmenv.tbsite.net

Caused by: java.net.UnknownHostException: jmenv.tbsite.net
	at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:567)
	at java.base/java.net.Socket.connect(Socket.java:751)

原因是, 默认情况下 Nacos 是以集群模式启动的, 直接在启动参数中添加: -Dnacos.standalone=true 以单机模式启动

posted @ 2026-03-27 22:46  daidaidaiyu  阅读(18)  评论(0)    收藏  举报