Nacos

目录

[Nacos 基本介绍](#Nacos 基本介绍)

[Nacos 安装](#Nacos 安装)

[Nacos 快速上手](#Nacos 快速上手)

引入依赖

[配置 Nacos 地址](#配置 Nacos 地址)

远程调用

启动服务

测试负载均衡

[Nacos 负载均衡](#Nacos 负载均衡)

服务下线

权重配置

同集群优先访问

健康检查

[Nacos 服务实例类型](#Nacos 服务实例类型)

[Nacos 环境隔离](#Nacos 环境隔离)

[Nacos 配置中心](#Nacos 配置中心)

[Data Id](#Data Id)


Nacos 基本介绍

NacosNaming and Configuration Service )是阿里巴巴 开源的一个动态服务发现、配置管理和服务管理平台,主要用于构建云原生应用的微服务架构。它提供了一套简单易用的 API 和控制台,帮助开发者实现服务注册与发现、动态配置管理、服务元数据管理以及服务健康监控等功能

目前,Nacos 几乎支持了所有的主流语言,如 Java、C++、Go、Nodejs、Python 等

Nacos 官网:https://nacos.io/

接下来,我们就来安装并使用 Nacos

Nacos 安装

可以直接从官网下载(Nacos Server 下载 | Nacos 官网)或 GitHub(Releases · alibaba/nacos

将压缩包解压到非中文目录下,进入 bin 目录:

其中:

startup.cmd:windows 平台启动脚本

startup.sh:linux 平台启动脚本

shutdown.cmd:windows 平台停止脚本

shutdown.sh:linux 平台停止脚本

Nacos 默认启动方式为集群 ,在学习阶段使用 单机 即可,因此我们修改配置为单机模式

打开startup.cmd 修改启动模式

将其修改为 standalone

修改后双击startup.cmd 启动:

访问 Nacos 主页:http://127.0.0.1:8848/nacos

Nacos 启动成功

Nacos 启动后,bin 目录下会生成logs 文件夹 ,存放Nacos 相关日志,若启动过程中出现问题,可查看日志进行分析和定位问题

Nacos 快速上手

引入依赖

父工程的 pom 文件 中引入Spring Cloud Alibaba依赖:

XML 复制代码
    <properties>
        <spring-cloud-alibaba.version>2022.0.0.0-RC2</spring-cloud-alibaba.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>
        </dependencies>
    </dependencyManagement>

在引入依赖时,需要注意版本之间的对应关系版本发布说明-阿里云Spring Cloud Alibaba官网

order-serviceproduct-service 中引入Nacos 依赖 和Load Balance依赖:

XML 复制代码
        <dependency> <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-loadbalancer</artifactId>
        </dependency>

配置 Nacos 地址

application.yml 中配置Nacos 地址

java 复制代码
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

远程调用

修改 OrderService 远程调用代码,将IP 和端口号 修改为 项目名称

java 复制代码
@Service
public class OrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private RestTemplate restTemplate;
    public OrderInfo findOrderInfoById(Integer orderId) {
        OrderInfo orderInfo = orderMapper.selectOrderById(orderId);
        String url = "http://product-service/product/" + orderInfo.getProductId();
        ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);
        orderInfo.setProductInfo(productInfo);
        return orderInfo;
    }
}

restTemplate 添加**@LoadBalanced**注解:

java 复制代码
@Configuration
public class BeanConfig {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

启动服务

启动order-serviceproduct-service ,观察nacos 管理界面

测试接口 127.0.0.1:8080/order/1

测试负载均衡

启动多个product-service

观察 Nacos 控制台:

多次访问接口,观察日志,测试负载均衡:

更多的时候,我们需要对服务流量进行更精细的控制,而 Nacos支持多种负载均衡策略,如权重、同机房、同地域、同环境等

接下来,我们就来具体看一下 Nacos 的具体负载均衡策略

Nacos 负载均衡

服务下线

当某个节点上接口的性能较差时,我们可以第一时间对该节点进行下线

点击下线后,该实例则没有请求再进来了:

上线后,该节点继续接收到请求:

除了对节点进行上下线操作,我们还可以配置这个节点的流量权重

权重配置

编辑对应节点,修改权重值:

节点的默认权重为1,此时将其修改为 0.2

然而,此时多次访问接口,观察日志,我们会发现 9090 端口实例接收的请求并没有变少

这是由于Spring Cloud LoadBalance 组件自身有负载均衡配置方式,因此不支持 Nacos 的权重属性配置,我们需要开启 Nacos 的负载均衡策略,让权重配置生效:

java 复制代码
spring:
  cloud:
    loadbalancer:
      nacos:
        enabled: true

此时再次启动服务,多次访问接口,就会发现 9090 端口实例接收的请求明显比另外两个实例少

同集群优先访问

Nacos 将同一个机房内的实例 ,划分为一个集群 ,因此同集群优先访问 ,在一定程度上也可以理解为同机房优先访问

在微服务架构中,一个服务通常由多个实例共同提供服务,这些实例可以部署在不同的机器上,而这些机器可能会分布在不同机房:

因此,微服务访问时,应尽量访问同机房的实例,当本机房内实例不可用时,才访问其他机房实例:

我们为 product-service 实例配置集群名称:

java 复制代码
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
        cluster-name: BJ # 北京集群

重启 9090 实例,观察 Nacos 控制台,BJ 集群下多了一个实例:

VM Option 中设置 9091端口号实例集群为 BJ:

-Dspring.cloud.nacos.discovery.cluster-name=BJ

同样为 9092 端口号实例设置集群为 CD:

-Dspring.cloud.nacos.discovery.cluster-name=CD

重启,观察 Naos 集群实例:

为 order-service 配置集群名称为 BJ:

java 复制代码
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
        cluster-name: BJ # 北京集群
    loadbalancer:
      nacos:
        enabled: true

多次访问接口,观察日志,发现只有 9090 和 9091 端口实例接收到了请求(同集群)

将 9090 端口实例 和 9091 端口实例都下线,再次访问接口,此时 9092 端口实例接收到了请求

健康检查

Nacos 作为注册中心,需要感知服务的健康状态,才能为服务调用方提供良好的服务

Nacos 中提供了两种健康检查机制

客户端主动上报机制

服务实例(客户端)每隔 5 秒 向 Nacos Server 发送一次 心跳(Beat)

Nacos Server 收到心跳后,会更新该实例的 最后心跳时间(lastBeat)

如果 15 秒内未收到心跳 ,Server 会将实例标记为 不健康(unhealthy)

如果 30 秒内仍未收到心跳 ,Server 会将实例 自动剔除(注销)

服务器反向探测机制

Nacos Server 主动发起探测

周期性检查目标实例的端口或健康接口是否可达

若探测失败,标记为不健康

在 Nacos 中,健康检查机制不能主动设置,而是跟 Nacos 的 服务实例类型强相关

Nacos 服务实例类型

Nacos 的服务实例(注册的节点)分为 临时实例非临时实例

临时实例: 生命周期短暂 ,依赖客户端主动上报心跳 维持存活,若客户端停止发送心跳(如进程崩溃、网络中断),Nacos Server 会在一定时间后自动将其实例注销(从服务列表中移除)

非临时实例: 生命周期持久不会因心跳中断而自动下线 ,即使服务宕机,实例仍会保留在 Nacos 服务列表中,需手动删除或通过服务端主动探测判定健康状态

Nacos 中,临时实例 采取客户端上报机制非临时实例 采取服务器反向探测机制

观察 Nacos 控制台 ,可以看到默认实例类型临时实例

我们将order-service实例配置为永久实例:

java 复制代码
spring:
  cloud:
    nacos:
      discovery:
        ephemeral: false # 设置为非临时实例

重启 order-service 服务:

重启失败,因为 order-service 为临时服务,无法注册持久化实例

Nacos 会记录每个服务实例的 IP 和 端口号,当发现IP 和 端口号都没有发生变化时,Nacos 不允许一个服务实例类型发生变化(临时实例 -> 非临时实例,或 非临时实例 -> 临时实例)

要解决这个问题,我们需要停掉 Nacos 并删除 Nacos 目录下的 \data\protocol\raft 信息,其中保存了应用实例的元数据信息

此时再重启 order-service,观察 Nacos 控制台:

order-service为非临时实例

Nacos 环境隔离

一个服务通常会分为开发环境、测试环境生产环境

开发环境:开发人员用于开发的服务器,是最基础的环境,一般日志级别设置较低,可能会开启一些调试信息

测试环境:测试人员用来进行测试的服务器,是开发环境到生产环境的过渡环境

生产环境:正式提供对外服务的环境,通常会关闭调试信息

通常情况下,这几个环境是不能互相通信的,Nacos 提供了namespace(命名空间) 来实现环境的隔离,不同的 namespace 服务不可见

默认情况下,所有的服务都在一个namespace(public) 中:

在命名空间中,可以对 namespace 进行操作:

新增命名空间:

配置 namespace ,修改 order-service 命名空间

java 复制代码
spring:
  cloud:
    nacos:
      discovery:
        namespace: 02153306-6b02-40eb-9027-4916554cb411 # 命名空间ID

重启服务,观察 Nacos 控制台:

此时再访问接口,进行远程调用测试:

product-service 实例不可用

我们将 product-service的其中一个实例命名空间修改为 test:

java 复制代码
spring:
  cloud:
    nacos:
      discovery:
        namespace: 02153306-6b02-40eb-9027-4916554cb411 # 命名空间ID

再次访问,远程调用成功:

Nacos 配置中心

除了注册中心和负载均衡外,Nacos 还是一个配置中心,具有配置管理的功能

若项目的配置都在代码中,就会存在以下问题:

  1. 配置文件修改后,服务需要重新部署,微服务架构中,一个服务可能有成百个实例,挨个部署会比较麻烦,且容易出错

  2. 多人开发时,配置文件可能经常需要修改,使用同一个配置文件容易出错

配置中心就是对这些配置项进行统一管理,通过配置中心,可以集中查看、修改和删除配置,无需再逐个修改配置文件,提高效率的同时,也降低了出错的风险

  1. 服务启动时,从配置中心读取配置项内容,进行初始化

  2. 配置项修改时,通知微服务,实现配置的更新加载

在 Nacos 控制台添加配置项:

新增配置项:

Data ID 设置为项目名称,配置格式 为配置内容的数据格式,再设置配置内容

引入 Nacos Config 依赖:

XML 复制代码
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <!-- SpringCloud 2020.*之后版本需要引⼊bootstrap-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>

配置bootstarp.properties (或 bootstarp.yml):

微服务启动前,需要先获取nacos 中的配置 ,并与 application.yml 配置合并 ,在微服务运行之前,Nacos 要求使用 bootstarp.properties(或bootstarp.yml ) 配置文件来配置 Nacos Server 地址**:**

java 复制代码
spring:
  application:
    name: product-service
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848

其中,spring.application.name 需要和 nacos 配置管理的 Data ID( 也就是项目名称**)**一致

spring.cloud.nacos.config.server-addr 为 Nacos Server 的地址

配置中心和注册中心的配置是隔离的

Nacos 配置中心:spring.cloud.nacos.config.server-addr

Nacos 注册中心:spring.cloud.nacos.discovery.server-addr

获取配置:

java 复制代码
@RequestMapping("/config")
@RefreshScope
@RestController
public class NacosController {
    @Value("${nacos.test.num}")
    private Integer nacosNum;

    @RequestMapping("/get")
    public Integer get() {
        return this.nacosNum;
    }
}

@Value:读取配置

@RefreshScope:配置进行热更新

启动product-service 9090 ,访问接口 127.0.0.1:9090/config/get

Nacos 控制台 修改nacos.test.num

再次访问接口:

Nacos配置管理的命名空间服务列表的命名空间分别设置的,默认为 public

服务列表的命名空间设置

Nacos 配置管理的命名空间 可在bootstarp.properties中设置:

配置管理设置命名空间后,项目启动时,会从该命名空间下找对应配置项:

访问接口 127.0.0.1:9090/config/get

Data Id

Nacos Spring Cloud 中,dataId完整格式为:

{prefix}-{spring.profiles.active}.{file-extension}** **{prefix}: 默认为spring.application.name 的值,也可以通过配置项 spring.cloud.nacos.config.prefix 来配置

{spring.profiles.active}:当前环境对应的 profile** ,若 **spring.profiles.active** 为空,对应 dataId 拼接为 **{prefix}.${file-extension}

${file-extension}:配置内容的数据格式 ,可通过配置项spring.cloud.nacos.config.file-extension 来配置

微服务启动时,会从 Nacos 中读取多个配置文件

{prefix}-{spring.profiles.active}.${file-extension} ,如product-service-dev.properties

{prefix}.{file-extension} ,如 product-service.properties

${prefix} ,如product-service

spring.application.name 、spring.profiles.active 等通过配置文件指定时,必须放在 bootstrap.properties(或bootstrap.yml ) 文件中

bootstrap.yml 中添加spring.profiles.active 值:

java 复制代码
spring:
  profiles:
    active: dev

启动服务,观察日志:

三个文件的优先级为:product-service-dev.properties > product-service.properties > product-service

我们来测试一下:

添加配置:

访问接口 127.0.0.1:9090/config/get

此时服务获取到了 product-service-dev.properties的值

删除 product-service-dev.properties 配置,再次访问接口:

此时服务获取到了 product-service.properties的值

删除 product-service.properties 配置,再次访问接口:

此时服务获取到了 product-service的值

相关推荐
ShadowSmartMicros2 小时前
SpringAi调用Mcp
java·ai
MediaTea2 小时前
思考与练习(第四章 程序组成与输入输出)
java·linux·服务器·前端·javascript
bailaoshi6662 小时前
Spring WebFlux整合reactor-rabbitmq
spring·rabbitmq·java-rabbitmq
kong79069282 小时前
Java新特性-(四)方法与数组
java·数组·方法
麦麦鸡腿堡2 小时前
Java_反射暴破创建对象与访问类中的成员
java·开发语言
大海星辰7982 小时前
工厂模式与策略模式的深度实践:从代码优化到架构思考
java·架构·策略模式
Jack_abu2 小时前
详解java中的线程间协作工具:CountDownLatch,Semaphore,CyclicBarrier(二)
java·并发编程·juc
miss_you12132 小时前
结算模块设计
java
派大鑫wink2 小时前
【Day1】Java 入门:开发环境搭建(JDK 安装 + IDEA 配置 + HelloWorld 实战)
java·开发语言·intellij-idea