Spring Cloud: Nacos配置中心与注册中心的使用

一、配置中心(配置管理)

配置中心是一种集中化管理配置的服务。它的主要作用包括集中管理配置信息,将不同服务的配置信息集中存储和管理;支持动态更新配置,通过操作界面或 API 无需重启服务即可应用最新配置信息;实现配置信息共享,不同服务实例可以共享同一套配置信息;提供配置信息的安全管理和权限控制功能;支持配置版本管理和历史记录,方便信息追溯。通过这些功能,配置中心帮助开发者简化配置管理,提高系统的灵活性和安全性。

1. 创建配置信息(新建配置)

配置管理.配置列表点击创建配置.

输入下图信息.

参数说明:

  • 命名空间: Nacos 基于命名空间(Namespace)帮助用户逻辑隔离多个命名空间,这可以帮助用户更好的管理测试、预发、生产等多环境服务和配置,让每个环境的同一个配置(如数据库数据源)可以定义不同的值。
  • Data ID: 配置的唯一标识,用于查找配置文件。
  • Group: 配置分组,用于设置小组信息,例如 DEV_GROUP 开发小组,TEST_GROUP 测试小组。

然后点击发布, 就新建了配置, 跳转到配置管理页.


以下是Nacos配置中心部分的功能展示.

如果需要修改, 可以点击编辑.

点击发布可以看到修改前后的比较, 绿色为新增, 红色为删除.

假如不小心修改错了, Nacos支持历史版本的回滚, 所以可以进行回滚.

点击**历史版本,**可以看到刚才所做的两个版本.

可以点击回滚进行回滚, 还可以查看当前版本和所点历史版本的比较.


2. Spring Boot 使用配置中心(实现配置中心的读取)

示例版本:

  • 开发环境: JDK 17+
  • Spring Boot 3.x (该版本最低要求JDK版本为JDK17+)
  • Spring Cloud 2022.0.0/Spring Cloud Alibaba 2022.0.0.0

接下来我们实现读取前文配置的myconfig内容.

2.1 创建项目

2.2 设置Nacos连接信息

在application.properties中我们可以看到Alibaba已经给我们设置好了相关模板.

我们需要修改一些必要的配置, 如下图已经标出.

博主修改的配置信息如下:

spring.cloud.nacos.config.server-addr=localhost:8848

spring.config.import=nacos:nacos-config-example

2.3 读取配置中心的配置信息

创建TestController.

java 复制代码
package com.example.demo.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {
    @Value("${myconfig}")
    private String myconfig;

    @RequestMapping("/getconfig")
    public String getMyconfig() {
        return myconfig;
    }
}

运行之后我们直接访问, 可以看到我们已经读取到了配置信息.


value使用的是懒加载的机制, 当在Nacos控制台修改了配置信息之后, 我们刷新我们的getconfig, 所修改的信息无法及时显示到页面上, 于是我们需要在controller类上添加 @RefreshScope 注解来实现value值的动态刷新. 然后重启程序.

然后我们修改对应配置, 再去刷新getconfig页面, 可以看到修改后的信息.

二、注册中心 (服务管理)

2.1 创建Spring Boot多模块项目

建父模块

创建好Project后, ++删除src.++

修改父模块的pom.xml

修改①: -RC2为候选版本, 删除后为正式版;

修改②: 已经删除了src, 所以相应的启动类也删除;

修改③: 该模块是父模块, 所以进行标识, 添加标识;

建子模块(生产者模块创建)

本来需要添加discover, 然而父模块已经有了, 那么此处什么也不需要, 直接创建. (该步在后续需要手动创建resources)

修改子模块的pom.xml

修改①: 该定义版本父模块已经有了;

修改②: 不需要做版本声明, 父模块已经声明全了;

修改③: 声明父模块;

修改④: 在父模块的pom.xml中声明子节点有哪些. 打包的时候使用, 有了这个之后就会按照声明的顺序进行打包.

最后点击Maven的刷新, 只要没有报错, 子模块就建好了.

2.2 添加 Nacos discovery 框架支持

前文建父模块的时候已经建好了discovery了, 所以这一步就算是完成了.

2.3 配置 Nacos 配置中心

在resources中添加application.yml

2.4 写接口

java 复制代码
package org.example.provider.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/getnamebyid")
    public String getNameById(Integer id) {
        return "provider-name-" + id;
    }
}

此时我们就可以启动项目了. 启动成功后这个服务也会被注册到 Nacos 中, 如下在服务列表中可以看到.


测试服务接口的使用

在这个服务的详情中可以看到它的所有节点, 如图中下方.

我们就可以通过IP+端口+路径的方式去调用这个服务.

如果需要把端口号打印出来, 由于是动态端口, 所以我们借助Servlet来实现.

重启这个服务, 我们会看到这个端口号不是原来的了.

那么我们来访问一下这个.


接下来我们尝试创建多个服务, 也就是创建多个provider, 在IDEA中进行复制, 然后就可以启动第二个实例, 在Nacos中我们就可以看到两个节点.


报错处理

这两个服务我们是可以把其中一个服务下线的.

下线之后, 就已经不能访问了, 我们常用这个来进行灰度发布. 但是这里点击下线的时候可能会出现报错. 那么所有Nacos在这里发生的报错, 都通过删除protocol文件夹来解决.


注册中心参数说明

分组名称 : 做逻辑隔离, 可能分不同环境. 通常不设置

健康实例数: 当前提供的服务有哪些.

当前已经开启了两个服务, 健康实例数为2.那么把其中一个服务停止之后, 就会变成1.

触发保护阈值: 防止服务雪崩.

比如这个集群中有1000个实例, 其中有999个都挂了, 只剩下1个, 此时将所有的请求给到这1个实例的话, 就会造成服务瘫痪, 于是就会造成上游调用这个服务整体的瘫痪, 就造成了服务雪崩.

当该值变为true时, 就会将所有实例(无论是否健康)全部给到消费者, 以此来保护剩下的健康实例.

再看服务详情中的参数.

保护阈值 : 健康节点要求的最小百分比。用于在服务出现不健康实例时,阻止流量过度向少量健康实例集中,保护服务的整体可用性。**保护阈值应设置为一个0到1之间的浮点数,默认值为 0。**当集群中的健康实例占比小于设置的保护阈值时,就会触发阈值保护功能。触发保护阈值后,Nacos 会将全部实例(健康实例+非健康实例)返回给调用者,虽然可能会损失一部分流量,但能保证集群中剩余的健康实例能正常工作。

服务路由类型: 用于实现不同的路由需求,常见的路由类型有以下两种:

  • none:默认路由,基于权重的轮询负载均衡路由策略
  • label:标签路由,相同标签的实例会被聚合为一个集群,不同标签则实现流量隔离。

临时实例 : Nacos 中的实例分为临时实例和永久实例(也叫持久实例),临时实例的生命周期和服务的运行周期相同,服务停止运行 Nacos 中就会将临时实例删除; 而永久示例即时程序终止, 也会保留在 Nacos 中. 在配置文件中通过: ++spring.cloud.nacos.discovery.ephemeral=true++ 设置.
权重 : 用于实现负载均衡,取值范围 0 到 10000,数值越大,权重越大,负载均衡被分配的概率也就越高. 设置为 0 的时候表示下线.

临时实例 VS 永久实例

永久实例(persistent instance)和临时实例(ephemeral instance)是注册中心的两种不同的服务类型。
永久实例(Persistent Instance): 是指注册到 Nacos 的服务实例,其注册信息会一直保留在Nacos 服务器上,直到主动注销或被删除。这意味着即使服务实例下线或不可用,它的注册信息仍然会保留在 Nacos 上,直到显式取消注册。永久实例适用于需要长期存在的服务,比如稳定部署的服务或长时间运行的后端服务。
**临时实例(Ephemeral Instance):**是指注册到 Nacos 的服务实例,其注册信息在实例下线或不可用时会自动被删除。如果服务实例下线、断开连接或主动注销,Nacos 会自动从注册表中删除这些实例的信息。临时实例适用于临时性的服务实例,比如临时加入集群的短期任务或特定场景下的临时服务。

健康检测机制

Nacos 中的健康检测机制是用来检查服务健康状态的,只有健康的节点才会被服务消费端调用,这样才能保证程序稳定、正常的运行。

Nacos 中提供了两种健康检测的机制:

  1. 客户端主动上报(健康状态的)机制,
  2. 服务器端反向探测(健康状态的)机制。

健康检查机制应用

Nacos 中的两种服务实例分别对应了两种健康检查机制:

  1. 临时实例(也可以叫做非持久化实例): 对应的是客户端主动上报机制。
  2. 永久实例(也可以叫做持久化实例) :服务端反向探测机制。

2.5 消费者模块

添加框架支持

前面父节点已经添加, 此处新建子模块即可.

  1. Nacos discovery
  2. Spring Cloud Loadbalancer
  3. Spring Cloud OpenFeign

修改子模块pom.xml

修改①: 声明父模块;

修改②: 删除父模块中已经有的配置;

在父模块中添加消费者子模块的声明.

最后点击Maven刷新.

配置Nacos

开启OpenFeign功能

在模块启动类上加上注解 @EnableFeignClients

声明OpeFeign式的Service(声明生产者服务)

java 复制代码
package org.example.consumer.service;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Service
@FeignClient("nacos-discovery-demo")    // 表示调用 Nacos 中的 nacos-discovery-demo 服务
public interface UserService {
    @RequestMapping("/user/getnamebyid")    // 调用生产者的 "/user/getnamebyid" 接口
    public String getNameById(@RequestParam("id") int id);
}

调用生产者服务

java 复制代码
package org.example.consumer.controller;

import org.example.consumer.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class BusinessController {
    @Autowired
    private UserService userService;

    @RequestMapping("/getnamebyid")
    public String getNameById(Integer id) {
        return userService.getNameById(id);
    }
}

启动运行之后访问(同时启动生产者的两个服务), 可以看到两个端口的轮询访问.

然而在Nacos中出现了一个nacos-consumer-demo, 这个是我们不需要的, 因为它是消费者, 而消费者只需要去调用生产者, 生产者进行服务注册, 消费者是不需要进行服务注册的, 而这里注册了, 就可能被调用, 所以我们就需要进行单独的设置.

再次重启, Nacos中就没有消费者的服务了. (不过调用的时候不影响)

2.6 如何注册一个永久实例

将前面运行的实例全部停掉, 此时在Nacos中就可以看到服务列表就已经不存在服务了.

接下来我们来创建一个永久实例.

在provider的yml中添加ephemeral属性, 其默认值为true, 我们将其设为false.

再次启动后可以在Nacos中看到, 临时实例已经变为false了.

此时如果我们把服务停掉, 再次刷新Nacos, 会看到这个实例已经永久在这里了(除非将protocol文件夹删除), 健康状态为false. 此时在服务列表中可以看到, 健康实例数为0, 也触发了保护阈值.

注意, 此时再启动, 健康实例数会变为1, 实例数是变成2. 因为是随机的端口, 也就是说下线的端口(临时端口)永久的不会再上线了. 保护阈值也为false, 因为要求最低的实例数为0.

这个时候启动consumer, 我们再去调用, 就只会调用35677端口.

演示保护阈值: 如果只剩下一个实例的时候想保护它怎么办? 在编辑服务中设置保护阈值(0~1).

设置触发保护阈值的值为0.5, 此时触发了为true.

我们重启一下, 再去访问url会发现它感知信息的有延迟的.

第一次

第二次

再访问一次

再访问一次

这种效果就是触发了保护阈值, 把错误的也返回出来了.

此时把它设置为不触发的状态, 比如0.3, 此时保护阈值就是false

再去访问就会看到不会有500错误的发生, 正因为是保护阈值没有被触发.


三、注册中心的交互流程

注册中心通常有两个角色:

  1. 服务提供者(也叫生产者):对外提供服务的微服务应用。它会把自身的服务地址注册到注册中心,以供消费者发现和调用。
  2. 服务调用者(也叫消费者):调用其他微服务的应用程序。它会向注册中心订阅自己需要的服务,并基于服务提供者注册的信息发起远程调用。

从图中我们可以看到 Nacos 注册中心在微服务架构中的交互流程。下面详细介绍各个组件之间的交互过程:

注册中心交互流程

  1. 服务提供者注册

服务提供者(Provider A、B、C)在启动时,会将自己的服务信息(如服务名称、实例地址、端口号等)注册到 Nacos 注册中心。

Nacos 注册中心会保存这些注册信息,并定期进行健康检测,确保服务实例是健康可用的。

  1. 服务发现

客户端需要调用某个服务时,向 Nacos 注册中心发送服务发现请求,查询目标服务的实例列表。

Nacos 注册中心根据请求查询内部存储,返回目标服务的健康实例列表给客户端。

  1. 负载均衡

客户端接收到服务实例列表后,通过负载均衡器选择一个服务实例(如服务提供者 B)进行调用。

负载均衡器根据配置的负载均衡策略(如轮询、随机、最少连接等),选择最合适的服务实例进行服务调用。

相关推荐
王彬泽2 小时前
【微服务】组件、基础工程构建(day2)
微服务
Cikiss2 小时前
微服务实战——SpringCache 整合 Redis
java·redis·后端·微服务
Cikiss2 小时前
微服务实战——平台属性
java·数据库·后端·微服务
杨荧4 小时前
【JAVA开源】基于Vue和SpringBoot的洗衣店订单管理系统
java·开发语言·vue.js·spring boot·spring cloud·开源
攸攸太上6 小时前
JMeter学习
java·后端·学习·jmeter·微服务
妍妍的宝贝7 小时前
k8s 中微服务之 MetailLB 搭配 ingress-nginx 实现七层负载
nginx·微服务·kubernetes
架构师吕师傅8 小时前
性能优化实战(三):缓存为王-面向缓存的设计
后端·微服务·架构
sdg_advance10 小时前
Spring Cloud之OpenFeign的具体实践
后端·spring cloud·openfeign
王彬泽11 小时前
【微服务】服务注册与发现、分布式配置管理 - Nacos
微服务·服务注册与发现·分布式配置管理
杨荧12 小时前
【JAVA开源】基于Vue和SpringBoot的旅游管理系统
java·vue.js·spring boot·spring cloud·开源·旅游