Alibaba微服务组件Nacos注册中心实战

文章目录

    • 注册中心介绍
      • 注册中心的作用
      • 注册中心设计思路分析
        • RestTemplate调用
        • 维护注册表
        • 注册中心
      • 注册中心对比
    • Nacos介绍
      • Nacos 注册中心架构和基本概念
      • Nacos注册中心核心功能
    • Nacos配置中心
      • Nacos配置中心的架构
    • [Nacos注册中心(Nacos Server)环境搭建 ](https://nacos.io/zh-cn/docs/deployment.html)
      • 单机模式
      • 集群模式
        • 配置nacos使用外置mysql数据源
        • 配置cluster.conf
        • mysql中创建nacos数据库
        • 分别启动nacos节点
    • Spring Cloud Alibaba Nacos快速开始
      • Spring Cloud Alibaba版本选型
      • 微服务接入配置中心
        • 引入依赖
        • 添加bootstrap.properties
        • 启动mall-order和mall-user,nacos管理端界面查看是否成功注册
        • 启动服务,测试微服务是否使用配置中心的配置
      • Config相关配置
        • 支持配置的动态更新
        • 支持profile粒度的配置
        • 支持自定义 namespace 的配置
        • 支持自定义 Group 的配置
        • 支持自定义扩展的 Data Id 配置
      • 配置的优先级
      • @RefreshScope实现动态感知
        • @RefreshScope 导致@Scheduled定时任务失效问题
        • 解决方案
    • Nacos注册中心常见配置
      • 服务分级存储模型
      • 服务逻辑隔离
      • Namespace 隔离设计
      • 临时实例和持久化实例

注册中心介绍

注册中心的作用

思考:不同的微服务如何维护复杂的调用关系?

//服务之间通过RestTemplate调用,url写死
String url = "http://localhost:8020/order/findOrderByUserId/"+id;
R result = restTemplate.getForObject(url,R.class);


实现服务发现的设计思路:
Alibaba微服务组件Nacos注册中心实战_第1张图片
服务注册中心的作用就是服务注册与发现 :

  • 服务注册:就是将提供某个服务的模块信息(通常是这个服务的ip和端口)注册到1个公共的组件上去。
  • 服务发现:就是新注册的这个服务模块能够及时的被其他调用者发现。不管是服务新增和服务删减都能实现自动发现


注册中心设计思路分析

RestTemplate调用

Alibaba微服务组件Nacos注册中心实战_第2张图片
存在问题及解决方案

场景 存在问题 解决方案
订单服务ip:port改变 需要修改代码 维护注册表
服务迁移 服务迁移ip改变,需修改代码 维护服务名与ip:port的关系
订单服务集群部署 需要代码中维护订单服务集群中每个节点ip:port,并实现负载均衡调用 维护注册表

维护注册表

Alibaba微服务组件Nacos注册中心实战_第3张图片
Alibaba微服务组件Nacos注册中心实战_第4张图片

场景 存在问题 解决方案
订单服务水平扩容 需手动修改注册表 注册表抽离为一个注册中心服务,扩容服务注册ip:port到注册中心【服务注册】
某个订单服务宕机 需手动修改注册表 注册表抽离为一个注册中心服务,可剔除宕机服务【服务剔除】

注册中心

Alibaba微服务组件Nacos注册中心实战_第5张图片

场景 存在问题 解决方案
服务调用 每次服务调用都从注册中心获取服务列表,耗时 本地服务也维护一份注册列表【本地注册表】
注册中心维护服务宕机 负载到宕机节点,调用失败 注册中心能发现宕机订单服务(心跳发现)【服务发现】

Alibaba微服务组件Nacos注册中心实战_第6张图片
注册中心能力:

  1. 注册接口【服务注册】:客户端启动主动调用注册
  2. 注销接口【服务剔除】:注册中心发现宕机客户端剔除
  3. 服务获取接口:客服端远程调用,获取服务列表,负责均衡远程调用
  4. 心跳检查【两种方案】
    1. 被动接受心跳,客户端定时发送到注册中心
    2. 主动检查心跳,注册中心广播调用注册列表服务

客户端(业务系统):

  1. 服务注册:启动注册服务
  2. 服务调用:客服端远程调用,获取服务列表,负责均衡远程调用
  3. 心跳检查:定时发送心跳到注册中心

注册中心对比

Alibaba微服务组件Nacos注册中心实战_第7张图片

Nacos介绍

   Nacos 是 Dynamic Naming and Configuration Service 的首字母简称;一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。

Nacos 的关键特性包括:

  1. 服务发现和服务健康监测
  2. 动态配置服务
  3. 动态 DNS 服务
  4. 服务及其元数据管理


官方文档 OpenAPI文档
nacos版本: v2.1.0

Nacos 优势

  1. 易用:简单的数据模型,标准的 restfulAPI,易用的控制台,丰富的使用文档。
  2. 稳定:99.9% 高可用,脱胎于历经阿里巴巴 10 年生产验证的内部产品,支持具有数百万服务的大规模场景,具备企业级 SLA 的开源产品。
  3. 实时:数据变更毫秒级推送生效;1w 级,SLA 承诺 1w 实例上下线 1s,99.9%
  4. 推送完成;10w 级,SLA 承诺 1w 实例上下线 3s,99.9% 推送完成;100w 级别,SLA 承诺 1w 实例上下线 9s 99.9% 推送完成。
  5. 规模:十万级服务/配置,百万级连接,具备强大扩展性。

Nacos 注册中心架构和基本概念

Alibaba微服务组件Nacos注册中心实战_第8张图片

概念 描述
服务 (Service) 服务是指一个或一组软件功能(例如特定信息的检索或一组操作的执行),其目的是不同的 客户端可以为不同的目的重用(例如通过跨进程的网络调用)。Nacos 支持主流的服务生态,如 Kubernetes Service、gRPC|Dubbo RPC Service 或者 Spring Cloud RESTful Service
服务注册中心 (Service Registry) 服务注册中心,它是服务及其实例和元数据的数据库。服务实例在启动时注册到服务注册 表,并在关闭时注销。服务和路由器的客户端查询服务注册表以查找服务的可用实例。服务 注册中心可能会调用服务实例的健康检查 API 来验证它是否能够处理请求
服务元数据 (Service Metadata) 服务元数据是指包括服务端点(endpoints)、服务标签、服务版本号、服务实例权重、路由 规则、安全策略等描述服务的数据
服务提供方 (Service Provider) 是指提供可复用和可调用服务的应用方
服务消费方 (Service Consumer) 是指会发起对某个服务调用的应用方

Nacos注册中心核心功能

核心功能 描述
服务注册 Nacos Client会通过发送REST请求的方式向Nacos Server注册自己的服务,提 供自身的元数据,比如ip地址、端口等信息。Nacos Server接收到注册请求后,就会把这 些元数据信息存储在一个双层的内存Map中
服务心跳 在服务注册后,Nacos Client会维护一个定时心跳来持续通知Nacos Server, 说明服务一直处于可用状态,防止被剔除。默认5s发送一次心跳
服务同步 Nacos Server集群之间会互相同步服务实例,用来保证服务信息的一致性
服务发现 服务消费者(Nacos Client)在调用服务提供者的服务时,会发送一个REST请 求给Nacos Server,获取上面注册的服务清单,并且缓存在Nacos Client本地同时会在Nacos Client本地开启一个定时任务定时拉取服务端最新的注册表信息更新到本地缓存
服务健康检查 Nacos Server会开启一个定时任务用来检查注册服务实例的健康情况,对 于超过15s没有收到客户端心跳的实例会将它的healthy属性置为false(客户端服务发时不 会发现),如果某个实例超过30秒没有收到心跳,直接剔除该实例(被剔除的实例如果恢复发 送心跳则会重新注册)

Nacos配置中心

Nacos 提供用于存储配置和其他元数据的 key/value 存储,为分布式系统中的外部化配置 提供服务器端和客户端支持。使用 Spring Cloud Alibaba Nacos Config,您可以在 Nacos Server 集中管理你 Spring Cloud 应用的外部属性配置。
Alibaba微服务组件Nacos注册中心实战_第9张图片

Nacos配置中心的架构

Alibaba微服务组件Nacos注册中心实战_第10张图片

    public static void main(String[] args) throws NacosException, InterruptedException {
        String serverAddr = "localhost:8848";
        String dataId = "nacos-config-demo.yaml";
        String group = "DEFAULT_GROUP";
        Properties properties = new Properties();
        properties.put(PropertyKeyConst.SERVER_ADDR, serverAddr);

        //获取配置中心服务
        ConfigService configService = NacosFactory.createConfigService(properties);

        //从配置中心拉取配置
        String content = configService.getConfig(dataId, group, 5000);
        System.out.println(content);
        //注册监听器
        configService.addListener(dataId, group, new Listener() {
            @Override
            public void receiveConfigInfo(String configInfo) {
                System.out.println("感知配置变化:" + configInfo);
            }

            @Override
            public Executor getExecutor() {
                return null;
            }
        });

        //发布配置
        //boolean isPublishOk = configService.publishConfig(dataId, group, "content");
        //System.out.println(isPublishOk);
        //发送properties格式
        configService.publishConfig(dataId,group,"common.age=30", ConfigType.PROPERTIES.getType());


        //        Thread.sleep(3000);
        //        //从配置中心拉取配置
        //        content = configService.getConfig(dataId, group, 5000);
        //        System.out.println(content);

        //        boolean isRemoveOk = configService.removeConfig(dataId, group);
        //        System.out.println(isRemoveOk);
        //        Thread.sleep(3000);

        //        content = configService.getConfig(dataId, group, 5000);
        //        System.out.println(content);
        //        Thread.sleep(300000);


        Thread.sleep(Integer.MAX_VALUE);

    }

Nacos注册中心(Nacos Server)环境搭建

单机模式

下载安装包
解压,进入nacos目录,单机模式启动nacos

#单机模式启动nacos
bin/startup.sh ‐m standalone

也可以修改默认启动方式
Alibaba微服务组件Nacos注册中心实战_第11张图片

集群模式

Nacos2.x版本相比1.X新增了gRPC的通信方式,因此需要增加2个端口。新增端口是 在配置的主端口(server.port)基础上,进行一定偏移量自动生成。
Alibaba微服务组件Nacos注册中心实战_第12张图片

配置nacos使用外置mysql数据源

修改conf/application.properties的配置,使用外置数据源

#使用外置mysql数据源
spring.datasource.platform=mysql

### Count of DB:
db.num=1

### Connect URL of DB:
db.url.0=jdbc:mysql://192.168.65.204:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user.0=root
db.password.0=root

配置cluster.conf

**将conf/cluster.conf.example改为cluster.conf,添加节点配置,**注意:不要使用localhost或127.0.0.1,针对多网卡环境,nacos可以指定网卡或ip

#多网卡选择
#ip‐address参数可以直接设置nacos的ip
#该参数设置后,将会使用这个IP去cluster.conf里进行匹配,请确保这个IP的值在cluster.conf里是存在的
nacos.inetutils.ip‐address=192.168.65.206

#use‐only‐site‐local‐interfaces参数可以让nacos使用局域网ip,这个在nacos部署的机器有多网卡时很有用,可以让nacos选择局域网网卡
nacos.inetutils.use‐only‐site‐local‐interfaces=true

#ignored‐interfaces支持网卡数组,可以让nacos忽略多个网卡
nacos.inetutils.ignored‐interfaces[0]=eth0
nacos.inetutils.ignored‐interfaces[1]=eth1

#preferred‐networks参数可以让nacos优先选择匹配的ip,支持正则匹配和前缀匹配
nacos.inetutils.preferred‐networks[0]=30.5.124.

mysql中创建nacos数据库

sql脚本

分别启动nacos节点

Alibaba微服务组件Nacos注册中心实战_第13张图片

Spring Cloud Alibaba Nacos快速开始

Spring Cloud Alibaba版本选型

Spring Cloud Alibaba版本选型
image.png
父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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0modelVersion>
  <parent>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring‐boot‐starter‐parentartifactId>
    <version>2.3.12.RELEASEversion>
    <relativePath/>
  parent>
  <groupId>com.tuling.mallgroupId>
  <artifactId>vip‐spring‐cloud‐alibabaartifactId>
  <version>0.0.1‐SNAPSHOTversion>
  <name>vip‐spring‐cloud‐alibabaname>
  <packaging>pompackaging>
  <description>Demo project for vip‐spring‐cloud‐alibabadescription>

  <properties>
    <java.version>1.8java.version>
    <spring.cloud.version>Hoxton.SR12spring.cloud.version>
    <spring.cloud.alibaba.version>2.2.8.RELEASEspring.cloud.alibaba.version>
  properties>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring‐cloud‐dependenciesartifactId>
        <version>${spring.cloud.version}version>
        <type>pomtype>
        <scope>importscope>
      dependency>
      <dependency>
        <groupId>com.alibaba.cloudgroupId>
        <artifactId>spring‐cloud‐alibaba‐dependenciesartifactId>
        <version>${spring.cloud.alibaba.version}version>
        <type>pomtype>
        <scope>importscope>
      dependency>

    dependencies>
  dependencyManagement>

project>

微服务接入配置中心

服务提供者可以通过 Nacos 的服务注册发现功能将其服务注册到 Nacos server 上。

引入依赖

当前项目pom中引入依赖

<dependency>
  <groupId>com.alibaba.cloudgroupId>
  <artifactId>spring‐cloud‐starter‐alibaba‐nacos‐discoveryartifactId>
dependency>

<dependency>
  <groupId>com.alibaba.nacosgroupId>
  <artifactId>nacos‐commonartifactId>
  <version>2.1.0version>
dependency>

注意:只引入spring-cloud-starter-alibaba-nacos-discovery包会出现下面的错误,还需 要再引入nacos-common包
image.png
此bug已经修复了,不需要再引入nacos-common了,只需要引入spring-cloud-starter和alibaba-nacos-discovery

添加bootstrap.properties

注意:必须使用 bootstrap.properties 配置文件来配置Nacos Server 地址

spring.application.name=nacos-config
# 配置中心地址
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
# 关闭配置中心
#spring.cloud.nacos.config.enabled = false

# dataid 格式: `${spring.application.name}-${profile}.${file-extension:properties}`
# dataid 为 yaml 的文件扩展名配置方式   nacos-config-dev.yaml
spring.cloud.nacos.config.file-extension=yaml
#profile粒度的配置,对应nacos-config-prod.yaml
spring.profiles.active=dev

在 Nacos Spring Cloud 中,dataId 的完整格式如下:
$ {prefix}-$ {spring.profiles.active}.${file-extension}

占位符 描述
prefix 默认为 spring.application.name 的值,也可以通过配置 项 spring.cloud.nacos.config.prefix来配置
spring.profiles.active 当前环境对应的 profile,详情可以参考 Spring Boot文档
file-exetension 配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置

注意:当 spring.profiles.active 为空时,对应的连接符 - 也将不存在,dataId 的拼接格式变成 p r e f i x . {prefix}. prefix.{file-extension}

更多配置

配置项 Key 默认值 说明
服务端地址 spring.cloud.nacos.discovery.server-addr Nacos Server 启动监听的ip地址和端口
服务名 spring.cloud.nacos.discovery.service ${spring.application.name} 给当前的服务命名
服务分组 spring.cloud.nacos.discovery.group DEFAULT_GROUP 设置服务所处的分组
权重 spring.cloud.nacos.discovery.weight 1 取值范围 1 到 100,数值越大,权重越大
网卡名 spring.cloud.nacos.discovery.network-interface 当IP未配置时,注册的IP为此网卡所对应的IP地址,如果此项也未配置,则默认取第一块网卡的地址
注册的IP地址 spring.cloud.nacos.discovery.ip 优先级最高
注册的端口 spring.cloud.nacos.discovery.port -1 默认情况下不用配置,会自动探测
命名空间 spring.cloud.nacos.discovery.namespace 常用场景之一是不同环境的注册的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。
AccessKey spring.cloud.nacos.discovery.access-key 当要上阿里云时,阿里云上面的一个云账号名
SecretKey spring.cloud.nacos.discovery.secret-key 当要上阿里云时,阿里云上面的一个云账号密码
Metadata spring.cloud.nacos.discovery.metadata 使用Map格式配置,用户可以根据自己的需要自定义一些和服务相关的元数据信息
日志文件名 spring.cloud.nacos.discovery.log-name
集群 spring.cloud.nacos.discovery.cluster-name DEFAULT 配置成Nacos集群名称
接入点 spring.cloud.nacos.discovery.enpoint UTF-8 地域的某个服务的入口域名,通过此域名可以动态地拿到服务端地址
是否集成Ribbon ribbon.nacos.enabled true 一般都设置成true即可
是否开启Nacos Watch spring.cloud.nacos.discovery.watch.enabled true 可以设置成false来关闭 watch
注册的IP地址类型 spring.cloud.nacos.discovery.ip-type IPv4 可以配置IPv4和IPv6两种类型

启动mall-order和mall-user,nacos管理端界面查看是否成功注册

Alibaba微服务组件Nacos注册中心实战_第14张图片

启动服务,测试微服务是否使用配置中心的配置

通过环境变量获取配置数据

@SpringBootApplication
public class NacosConfigApplication {

    public static void main(String[] args) throws InterruptedException {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(NacosConfigApplication.class, args);
        //当动态配置刷新时,会更新到 Enviroment中,因此这里每隔3秒中从Enviroment中获取配置
        String userName = applicationContext.getEnvironment().getProperty("common.name");
        String userAge = applicationContext.getEnvironment().getProperty("common.age");
        System.err.println("common name:" + userName + "; age: " + userAge);
    }
}

Alibaba微服务组件Nacos注册中心实战_第15张图片
使用RestTemplate进行服务调用
给 RestTemplate 实例添加 @LoadBalanced 注解,开启 @LoadBalanced 与 Ribbon 的 集成

@Configuration
public class RestConfig {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

调用逻辑

#使用微服务名发起调用
String url = "http://mall‐order/order/findOrderByUserId/"+id;
List<Order> orderList = restTemplate.getForObject(url, List.class);

Config相关配置

Nacos 数据模型 Key 由三元组唯一确定, Namespace默认是空串,公共命名空间 (public),分组默认是 DEFAULT_GROUP
Alibaba微服务组件Nacos注册中心实战_第16张图片

支持配置的动态更新
@SpringBootApplication
@EnableScheduling   // 开启定时任务功能
public class NacosConfigApplication {

    public static void main(String[] args) throws InterruptedException {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(NacosConfigApplication.class, args);
        while (true) {
            //当动态配置刷新时,会更新到 Enviroment中,因此这里每隔3秒中从Enviroment中获取配置
            String userName = applicationContext.getEnvironment().getProperty("common.name");
            String userAge = applicationContext.getEnvironment().getProperty("common.age");
            System.err.println("common name:" + userName + "; age: " + userAge);
            TimeUnit.SECONDS.sleep(3);
        }
    }
}

支持profile粒度的配置

   spring-cloud-starter-alibaba-nacos-config 在加载配置的时候,不仅仅加载了以 dataid 为 $ {spring.application.name}.$ {file-extension:properties} 为前缀的基础配置,还加载 了dataid为 $ {spring.application.name}-$ {profile}.${file-extension:properties} 的基础 配置。在日常开发中如果遇到多套环境下的不同配置,可以通过Spring 提供的 ${spring.profiles.active} 这个配置项来配置。

spring.profiles.active=dev

支持自定义 namespace 的配置

   用于进行租户粒度的配置隔离。不同的命名空间下,可以存在相同的 Group 或 Data ID 的 配置。Namespace 的常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生 产环境的资源(如配置、服务)隔离等。
在没有明确指定 ${spring.cloud.nacos.config.namespace} 配置的情况下, 默认使用的是 Nacos 上 Public 这个namespace。如果需要使用自定义的命名空间,可以通过以下配置来实现:

spring.cloud.nacos.config.namespace=71bb9785‐231f4eca‐b4dc‐6be446e12ff8

支持自定义 Group 的配置

   Group是组织配置的维度之一。通过一个有意义的字符串(如 Buy 或 Trade )对配置集进 行分组,从而区分 Data ID 相同的配置集。当您在 Nacos 上创建一个配置时,如果未填写配置分组的名称,则配置分组的名称默认采用 DEFAULT_GROUP 。
配置分组的常见场景: 不同的应用或组件使用了相同的配置类型,如 database_url 配置和 MQ_topic 配置。 在没有明确指定 ${spring.cloud.nacos.config.group} 配置的情况下,默认是 DEFAULT_GROUP 。如果需要自定义自己的 Group,可以通过以下配置来实现:

spring.cloud.nacos.config.group=DEVELOP_GROUP

支持自定义扩展的 Data Id 配置

   Data ID 是组织划分配置的维度之一。Data ID 通常用于组织划分系统的配置集。一个系 统或者应用可以包含多个配置集,每个配置集都可以被一个有意义的名称标识。Data ID 通 常采用类 Java 包(如 com.taobao.tc.refund.log.level)的命名规则保证全局唯一性。此 命名规则非强制。
   通过自定义扩展的 Data Id 配置,既可以解决多个应用间配置共享的问题,又可以支持一个 应用有多个配置文件。

# 自定义 Data Id 的配置
#不同工程的通用配置 支持共享的 DataId
spring.cloud.nacos.config.sharedConfigs[0].data‐id= common.yaml
spring.cloud.nacos.config.sharedConfigs[0].group=REFRESH_GROUP
spring.cloud.nacos.config.sharedConfigs[0].refresh=true

# config external configuration
# 支持一个应用多个 DataId 的配置
spring.cloud.nacos.config.extensionConfigs[0].data‐id=ext‐config‐common01.properties
spring.cloud.nacos.config.extensionConfigs[0].group=REFRESH_GROUP
spring.cloud.nacos.config.extensionConfigs[0].refresh=true

spring.cloud.nacos.config.extensionConfigs[1].data‐id=ext‐config‐common02.properties
spring.cloud.nacos.config.extensionConfigs[1].group=REFRESH_GROUP
spring.cloud.nacos.config.extensionConfigs[1].refresh=true

配置的优先级

Spring Cloud Alibaba Nacos Config 目前提供了三种配置能力从 Nacos 拉取相关的配置

标记 配置 描述
A spring.cloud.nacos.config.shared-configs 支持多个共享 Data Id 的 配置
B spring.cloud.nacos.config.ext-config[n].data-id 的方式支持多个扩展 Data Id 的配置
C 配置文件优先级 通过内部相关规则(应用名、应用名+ Profile )自动生成相关的 Data Id 配置 当三种方式共同使用时

优先级关系是:A < B < C
C优先级从高到低:
1、$ {spring.application.name}-{profile}.profile. {file-extension:properties}
2、$ {spring.application.name}.$ {file-extension:properties}
3、${spring.application.name}
4、extensionConfigs 一个微服务的多个配置,比如 nacos,mybatis
5、sharedConfigs 多个微服务公共配置,比如 redis

@RefreshScope实现动态感知

@Value注解可以获取到配置中心的值,但是无法动态感知修改后的值,需要利用@RefreshScope注解

@RestController
@RefreshScope  //动态感知修改后的值
public class TestController {

    @Value("${common.age}")
    String age;
    @Value("${common.name}")
    String name;

    @GetMapping("/common")
    public String hello() {
        return name+","+age;
    }
}

@RefreshScope 导致@Scheduled定时任务失效问题

启动类上添加@EnableScheduling // 开启定时任务功能
当利用@RefreshScope刷新配置后会导致定时任务失效

@RestController
@RefreshScope  //动态感知修改后的值
public class TestController {

    @Value("${common.age}")
    String age;
    @Value("${common.name}")
    String name;

    @GetMapping("/common")
    public String hello() {
        return name+","+age;
    }

    //触发@RefreshScope执行逻辑会导致@Scheduled定时任务失效
    @Scheduled(cron = "*/3 * * * * ?")  //定时任务每隔3s执行一次
    public void execute() {
        System.out.println("定时任务正常执行。。。。。。");
    }
}

当在配置中心变更属性后,定时任务失效
当再次访问http://localhost:8010/common,定时任务生效

原因:@RefreshScope修饰的bean的属性发生变更后,会从缓存中清除。此时没有这个bean,定时任务当然也就不生效了,详细原因如下:【核心源码:GenericScope#get】

  1. @RefreshScope 注解标注了@Scope 注解,并默认了 ScopedProxyMode.TARGET_CLASS属性,此属性的功能就是创建一个代理,在每次调用的时候都用它来调用GenericScope#get 方法来获取bean对象
  2. 在GenericScope 里面包装了一个内部类 BeanLifecycleWrapperCache 来对加了@RefreshScope 的bean进行缓存,使其在不刷新时获取的都是同一个对象
  3. 如属性发生变更会调用 ContextRefresher#refresh()—— >RefreshScope#refreshAll() 进行缓存清理方法调用,并发送刷新事件通知 ——> 调用GenericScope#destroy() 实现清理缓存
  4. 当下一次使用此bean对象时,代理对象会调用GenericScope#get(String name, ObjectFactory objectFactory) 方法创建一个新的bean对象,并存入缓存中, 此时新对象因为Spring 的装配机制就是新的属性了

解决方案

实现Spring事件监听器,监听 RefreshScopeRefreshedEvent事件,监听方法中进行一次定时方法的调用

@RestController
@RefreshScope  //动态感知修改后的值
public class TestController implements ApplicationListener<RefreshScopeRefreshedEvent>{

    @Value("${common.age}")
    String age;
    @Value("${common.name}")
    String name;

    @GetMapping("/common")
    public String hello() {
        return name+","+age;
    }

    //触发@RefreshScope执行逻辑会导致@Scheduled定时任务失效
    @Scheduled(cron = "*/3 * * * * ?")  //定时任务每隔3s执行一次
    public void execute() {
        System.out.println("定时任务正常执行。。。。。。");
    }

    @Override
    public void onApplicationEvent(RefreshScopeRefreshedEvent event) {
        this.execute();
    }
}

Nacos注册中心常见配置

服务分级存储模型

   注册中心的核心数据是服务的名字和它对应的网络地址,当服务注册了多个实例时,我们需 要对不 健康的实例进行过滤或者针对实例的㇐些特征进行流量的分配,那么就需要在实例 上存储㇐些例如 健康状态、权重等属性。随着服务规模的扩大,渐渐的又需要在整个服务 级别设定㇐些权限规则、 以及对所有实例都生效的㇐些开关,于是在服务级别又会设立㇐ 些属性。再往后,我们又发现单个 服务的实例又会有划分为多个子集的需求,例如㇐个服 务是多机房部署的,那么可能需要对每个机 房的实例做不同的配置,这样又需要在服务和 实例之间再设定㇐个数据级别。 Nacos 在经过内部多年生 产经验后提炼出的数据模型,则是㇐种服务-集群-实例的三层模 型。这样基本可以满足 服务在所有场景下的数据存储和管理。
Alibaba微服务组件Nacos注册中心实战_第17张图片

服务逻辑隔离

Nacos 数据模型 Key 由三元组唯一确定, Namespace默认是空串,公共命名空间 (public),分组默认是 DEFAULT_GROUP。
Alibaba微服务组件Nacos注册中心实战_第18张图片

Namespace 隔离设计

命名空间(Namespace)用于进行租户(用户)粒度的隔离,Namespace 的常用场景之一 是不同环境的隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。
Alibaba微服务组件Nacos注册中心实战_第19张图片
修改yml配置

spring:
    application:
    name: mall‐user #微服务名称
    cloud:
    nacos:
    discovery:
    server‐addr: 127.0.0.1:8848 #配置nacos注册中心地址
    namespace: bc50d386‐8870‐4a26‐8803‐0187486c57be # dev 开发环境

启动mall-user,进入nacos控制台可以看到mall-user注册成功,所属namespace是dev
Alibaba微服务组件Nacos注册中心实战_第20张图片
测试:http://localhost:8040/user/findOrderByUserId/1,报错
image.png
原因:mall-order和mall-user使用了不同的namespace,导致服务隔离。

group服务分组
不同的服务可以归类到同一分组,group也可以起到服务隔离的作用。yml中可以通过 spring.cloud.nacos.discovery.group参数配置

临时实例和持久化实例

   在定义上区分临时实例和持久化 实例的关键是健康检查的方式。临时实例使用客户端 上报模式,而持久化实例使用服务端反向探测模式。临时实例需要能够自动摘除不健康实 例,而且无需持久化存储实例。持久化实例使用服务端探测的健康检查方式,因为客户端不 会上报心跳, 所以不能自动摘除下线的实例。
在大中型的公司里,这两种类型的服务往往都有。㇐些基础的组件例如数据库、缓存等,这些往往不能上报心跳,这种类型的服务在注册时,就需要作为持久化实例注册。而上层的业务服务,例如 微服务或者 Dubbo 服务,服务的 Provider 端支持添加汇报心跳的逻辑,此时就可以使用动态服务的注册方式。
Nacos 1.x 中持久化及非 持久化的属性是作为实例的㇐个元数据进行存储和识别。 Nacos 2.x 中继续沿用了持久化及非持久化的设定,但是有了㇐些调整。在 Nacos2.0 中将 是否持久化的数据抽象至服务级别, 且不再允许㇐个服务同时存在持久化实例和非持久化 实例,实例的持久化属性继承自服务的持久化属性。

# 持久化实例
spring.cloud.nacos.discovery.ephemeral: false

你可能感兴趣的:(Spring,Cloud,Alibaba,java,微服务,spring,cloud)