Nacos注册中心和配置中心使用详情

Nacos

Nacos就是Alibaba推出的一款 配置中心和注册中心结合的一款工具,属于SpringCloudAlibaba技术栈下

Nacos官网地址

https://nacos.io/zh-cn/index.html

安装启动

下载

image.png

image.png

目录结构

根据目录结构可以看出Nacos本身也就是一个java程序。SpringBoot程序

image.png

image.png

启动

cmd窗口进入nacos的bin目录,因为我这里是windos

// windows 启动

# 启动命令:
startup.cmd
# 双击startup.cmd运行文件。
# 默认是集群启动,所以要指定 参数,单机启动

startup.cmd -m standalone

# Linux/Unix/Mac启动方式:
# 启动命令(standalone代表着单机模式运行,非集群模式)
sh startup.sh -m standalone
# 如果是ubuntu系统,或者运行脚本报错提示[[符号找不到,可尝试如下运行:
bash startup.sh -m standalone


image.png

控制台不要关闭,访问nacos的监控页面

默认的账号密码都是nacos,nacos

http://localhost:8848/nacos/

image.png

image.png

配置中心

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

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

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

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

nacos的配置中心,我们可以把Boot程序中的yaml配置写在nacos中。boot程序访问nacos中的配置

从而将公共的配置更方便的做处理

并且可以实现nacos配置改变,不重启项目的情况下,改变项目中的配置信息

新建配置

image.png

image.png

监听查询

image.png

JAVA的API操作NACOS

这里使用Nacos自带的api操作,了解这些之后,即使在SpringBoot中遇到问题也是可以使用原生api操作的

引入依赖

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

    <groupId>nacosBoot</groupId>
    <artifactId>nacosBoot</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!--引入父模块-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
    </parent>
    <properties>
        <nacos>2.1.1</nacos>
    </properties>

    <!--引入 Spring-Boot-starter依赖-->
    <dependencies>
        <!--从parent中引出的boot的web依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--引入nacos客户端依赖-->
        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
            <version>${nacos}</version>
        </dependency>
    </dependencies>
</project>

添加Nacos的配置文件

image.png

每次的添加和修改都会产生记录和历史数据

image.png

获取配置代码

public static void main(String[] args) {
        try {
            ConfigService configService = NacosFactory.createConfigService("127.0.0.1:8848");

            String dataId = "JavaTestNacos";
            String groupId = "JAVA_API";
            // 指定 DataID,GroupID,超时时间 从而指定nacos中的配置文件
            String config = configService.getConfig(dataId, groupId, 5000);
            System.out.println(config);

        } catch (NacosException e) {
            e.printStackTrace();
        }
    }

image.png

监听配置代码

 public static void main(String[] args) {
        try {
            ConfigService configService = NacosFactory.createConfigService("127.0.0.1:8848");
            String dataId = "JavaTestNacos";
            String groupId = "JAVA_API";

            // 指定 DataID,GroupID
            // 重写监听器的回调函数
            configService.addListener(dataId, groupId, new Listener() {
                @Override
                public Executor getExecutor() {
                    return null;
                }

                // 作为监听器的回调函数
                @Override
                public void receiveConfigInfo(String s) {
                    System.out.println("时间: "+ LocalDateTime.now());
                    System.out.println(s);
                }
            });

            // 避免main方法运行就结束
            System.out.print("避免程序结束:");
            System.in.read();

        } catch (NacosException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

image.png

SpringBoot操作

引入依赖

<!--引入nacos客户端依赖-->
        <dependency>
            <groupId>com.alibaba.boot</groupId>
            <artifactId>nacos-config-spring-boot-starter</artifactId>
            <version>0.2.12</version>
        </dependency>

image.png

方式一

配置类指定nacos的访问信息

@SpringBootApplication
@EnableNacosConfig(globalProperties = @NacosProperties(serverAddr = "127.0.0.1:8848"))
@NacosPropertySource(dataId = "SpringBootNacos",groupId = "DEFAULT_GROUP",autoRefreshed = true)
public class SpringBootNacosStudy {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootNacosStudy.class,args);
    }
}

@RestController
public class NacosProperties {

    @NacosValue(value = "${name}",autoRefreshed = true)
    String name;

    @GetMapping("/showProperties")
    public String showProperties(){
       return name;
    }

}

测试可以随着配置文件改变而改变

image.png

方式二

如果我们不想用配置类的注解方式我们还可以在配置文件中指定

其实底层,配置文件和注解都是进行绑定到配置类中的api操作

启动类不指定注解方式,使用配置类指定配置文件

contoller不用改变

@SpringBootApplication
public class SpringBootNacosStudy {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootNacosStudy.class,args);
    }
}
nacos.config.data-id=SpringBootNacos
nacos.config.group=DEFAULT_GROUP
nacos.config.server-addr=127.0.0.1:8848
nacos.config.auto-refresh=true
nacos.config.bootstrap.enable=true

image.png

SpringCloud操作Nacos

Nacos的Cloud和Boot对应的版本说明

Nacos 快速开始

image.png

引入依赖

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

    <groupId>nacosBoot</groupId>
    <artifactId>nacosBoot</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!--引入父模块-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
    </parent>

    <!--引入 Spring-Boot-starter依赖-->
    <dependencies>
        <!--从parent中引出的boot的web依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--引入nacos客户端依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
            <version>2.2.8.RELEASE</version>
        </dependency>
    </dependencies>
</project>

image.png

配置文件

SpringBoot中默认是不支持bootstrap.properties属性文件的。我们需要映入SpringCloud的依赖才可以。

Bootstrap.properties 配置文件主要是通过 SpringCloud 新增的父应用上下文通过 BootstrapApplicationListener 监听事件 来初始化 Bootstrap 应用上下文然后进行加载填充到 SpringApplication 的 Environment 中。

# 指定服务名称 同时指定DataId
spring.application.name=nacos-study

# 下面是指定 nacos的分组和地址
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.group=DEFAULT_GROUP

这里我指定了两个配置文件

bootStrap:指定 服务名和nacos相关信息

application:指定了一个age,与nacos中冲突测试会采用那边

image.png

注意:即使不编写BootStrap文件,将内容迁移application中项目也是可以正常运行

注意:即使不编写BootStrap文件,将内容迁移application中项目也是可以正常运行

注意:即使不编写BootStrap文件,将内容迁移application中项目也是可以正常运行

启动类和controller

@SpringBootApplication
public class SpringBootNacosStudy {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootNacosStudy.class,args);
    }
}

@RefreshScope

这个注解的作用不是开启Nacos的自动刷新

nacos自动刷新配置默认开启,这里表示的javaBean的属性自动刷新

// 注意这里使用的 @RefreshScope

@RestController
@RefreshScope
public class NacosProperties {

    @Value("${name}")
    String name;

    @Value("${age}")
    String age;

    @GetMapping("/showProperties")
    public String showProperties(){
        return name+" "+age;
    }

}

结果:发现最终配置类的age采用了项目中的配置

所以:项目中配置<nacos中配置

image.png

如果Nacos服务突然挂掉,不会影响服务正常运行

如果Nacos服务突然挂掉,不会影响服务正常运行

多个配置文件

# 指定服务名称 同时指定DataId
spring.application.name=nacos-study

我们可以在nacos中配置多个配置文件。

拉去顺序

拉去dataid等于 服务名称 的配置

拉去dataid等于 指定名称.properties  或 服务名称.yaml  的配置 
通过  spring.cloud.nacos.config.file.extension=properties/yaml 来决定
这里也表示读取到的 nacos的文件格式解析指定为 properties 还是 yaml 创建文件编写的格式

拉去dataid等于 服务名称-${spring.profiles.active}.properties的配置
spring.profiles.active=dev 就决定获取 服务名称-dev.proerties的dataid配置文件


// 指定后缀
spring.cloud.nacos.config.file.extension=properties/yaml
// 指定文件的-环境
spring.profiles.active=dev

可以自行去测试验证

image.png

指定多个配置文件

我们上面指定的配置文件,按照优先级也只是指定一个配置文件

我们可以通过上面配置文件指定多个自定义的配置文件

一个用于可能不止需要一个配置,有可能需要多个配置


spring.cloud.nacos.config.shared-configs[0].data-id=dataid全名字
spring.cloud.nacos.config.shared-configs[1].data-id=dataid全名字

spring.cloud.nacos.config.extension-configs[0].data-id=dataid全名字
spring.cloud.nacos.config.extension-configs[1].data-id=dataid全名字
优先级
  1. config[1] > config[0]:值越大优先级越搞
  2. nacos的主配置 > extension > shared

服务注册

nacos原生操作【服务注册】

引入依赖

		<!-- 需要引入的依赖-->
		 <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
            <version>2.1.1</version>
        </dependency>
		
		<!--不过引入 cloud的注册中心依赖会包含nacos的原生依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>2.2.8.RELEASE</version>
        </dependency>

代码操作

示例1
public class DemoOne {
    public static void main(String[] args) {
        try {
            // 创建一个nacos服务
            NamingService namingService = NamingFactory.createNamingService("127.0.0.1:8848");
            // 创建一个实例 指定参数
            Instance instance = new Instance();
            instance.setClusterName("testClusterName");
            instance.setIp("11.11.11.1");
            instance.setPort(9090);

            // nacos注册指定实例,指定服务名称
            namingService.registerInstance("testServerName",instance);

            // 防止程序运行停止
            System.in.read();

        } catch (NacosException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

image.png

示例2

直接写定参数来指定。不需要创建Instance实例


public class DemoTwo {
    public static void main(String[] args) {
        try {
            // 创建一个nacos服务
            NamingService namingService = NamingFactory.createNamingService("127.0.0.1:8848");
            // nacos注册指定 指定
            // 服务名称,ip,端口,集群名称
            namingService.registerInstance("testServerName","11.11.11.2",8888,"cluster1");

            NamingService namingService1 = NamingFactory.createNamingService("127.0.0.1:8848");
            namingService1.registerInstance("testServerName","11.11.11.3",8888,"cluster1");

            NamingService namingService2 = NamingFactory.createNamingService("127.0.0.1:8848");
            namingService2.registerInstance("testServerName","11.11.11.4",8888,"cluster2");

            // 防止程序运行停止
            System.in.read();

        } catch (NacosException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

image.png

这些服务都是上面的代码。注册到nacos中的

这些服务都是上面的代码。注册到nacos中的

这些服务都是上面的代码。注册到nacos中的

image.png

Nacos就是根据这些概念性的一层一层划分查找,一层一层找

NameSpace:命名空间,主要用来区分运行环境,开发,测试,生产

group:区分组,指定服务在那个组下,避免出现相同的服务名区分

service:服务名。多个服务在一起

cluster:将多个服务在分成一个一个的集群

image.png

-- 本服务的 ip 端口
server:
  port: 8001
  
spring:
  application:
-- 本服务的服务名
    name: WXL-DEV-SERVICE-2
  cloud:
    nacos:
-- 指定nacos的ip端口注册到位置
      server-addr: localhost:8848 # nacos的服务配置
      discovery:
-- 注册到的集群名称
        cluster-name: Service_cluster_2  #集群
-- 注册到的分组名称
        group: Service_group_2  # 分组名
        namespace: public  # 命名空间
        username: nacos # 用户名
        password: nacos # 密码
        ephemeral: false #永久实例 哪怕宕机了也不会删除实例,默认为true非永久 

nacos原生操作【服务发现】

获取nacos中的服务实例

NamingService的方法

方法名描述
getAllInstances指定服务名称,等参数。获取当前所有实例
selectInstances指定服务名,等参数。获取当前所有 健康实例
selectOneHealthyInstance指定服务,等参数。获取一个随机的 健康实例 根据权重,越高出现概率越高

Instance类

该类就表示获取的一个服务的所有信息,在注册的时候我也同样去指定过Instance

public class Primordial {
    public static void main(String[] args) throws NacosException {
        // 创建nocos 服务
        NamingService namingService = NamingFactory.createNamingService("127.0.0.1");

        // 指定服务名称获取当前所有实例
        List<Instance> testServerName = namingService.getAllInstances("testServerName");

        // 指定服务名成获取当前所有 健康实例
        List<Instance> instances = namingService.selectInstances("testServerName", true);

        // 指定服务名获取一个随机的 健康实例  根据权重,越高出现概率越高
        namingService.selectOneHealthyInstance("testServerName");

    }
}

修改服务的权重

image.png

监听获取实例

public class AutoPrimordial {
    public static void main(String[] args) throws NacosException, IOException {
        // 创建nocos 服务
        NamingService namingService = NamingFactory.createNamingService("127.0.0.1");

        // 创建监听事件 这里注意导包
        EventListener eventListener = new EventListener(){

            // 监听的回调函数
            @Override
            public void onEvent(Event event) {
                //  判断是否该类型
                if(event instanceof NamingEvent){
                    // 转换 事件名称 可以获取服务更改的信息
                    NamingEvent event1 = (NamingEvent) event;
                    String serviceName = event1.getServiceName();
                    String clusters = event1.getClusters();
                    List<Instance> instances = event1.getInstances();
                    for (Instance instance : instances) {
                        System.out.println("服务名称:"+instance.getServiceName());
                        System.out.println("集群名称:"+instance.getClusterName());
                        System.out.println("实例id:"+instance.getInstanceId());
                        System.out.println("ip:端口:"+instance.getIp()+instance.getPort());
                    }

                }
            }
        };

        // 指定监听订阅的服务名 和 事件监听的回调函数
        namingService.subscribe("testServerName",eventListener);

        System.in.read();
    }
}

可以通过修改注册进的服务实例,或者直接关闭注册进的服务。

从而动态的监听到变化,执行回调函数。

SpringCloud服务注册

这里我新建一个服务nacosProduce来模拟nacos的服务注册进去

引入依赖

<!--不过引入 cloud的注册中心依赖会包含nacos的原生依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>2.2.8.RELEASE</version>
        </dependency>
spring.application.name=produce

# 这里可以看到指定了两个 nacos的ip和端口
# 带上discovery 表示专门区分 配置中心和注册中心的nacos的配置
# 不带discovery 表示 配置中心和注册中心地址一样
spring.cloud.nacos.server-addr=127.0.0.1:8848
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

image.png

image.png

SpringCloud服务发现

因为想要测试,调用注册进去的服务是否可以访问到,我们可以在 produce服务中编写一个Contoller进行调用测试

@RestController
public class ProduceController {
    @GetMapping("/showProduce")
    public String showProduce(){
        return "我是produce服务";
    }
}

image.png

RestTemplate的服务调用

image.png

spring.application.name=consumer
server.port=2222
@RestController
public class consumerController {
    @GetMapping("consumer")
    public String consumer(){
        RestTemplate restTemplate = new RestTemplate();
        // 写死url 进行调用
        // 不能走注册中心 获取ip地址 和负载均衡
        ResponseEntity<String> forEntity = 
                restTemplate.getForEntity("http://localhost:1111/showProduce", String.class);
        String body = forEntity.getBody();
        return "consumer调用结果: "+body;
    }
}

使用nacos服务发现

引入依赖与服务注册那边一致

引入依赖与服务注册那边一致

引入依赖与服务注册那边一致

配置文件

指定nacos的ip地址

spring.application.name=consumer
server.port=2222
#  nacos的ip和端口
spring.cloud.nacos.server-addr=127.0.0.1:8848
主启动

开启服务注册中心

重新指定RestTemplate的类

LoadBalanced:当注册中心对服务名存在多个服务会进行负载均衡的调用

@SpringBootApplication
@EnableDiscoveryClient
public class Consumer {

    // loadBalanced 是负载均衡 存在多个规则。
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

    public static void main(String[] args) {
        SpringApplication.run(Consumer.class,args);
    }
}
Controller

路径通过服务名获取IP地址

@RestController
public class consumerController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("consumer")
    public String consumer() {
        // 写死url 进行调用
        // 不能走注册中心 获取ip地址 和负载均衡
        ResponseEntity<String> forEntity =
                restTemplate.getForEntity("http://produce/showProduce", String.class);
        String body = forEntity.getBody();
        return "consumer调用结果: " + body;
    }
}

RestTemplate的操作后面可以改下为feign调用形式

RestTemplate的操作后面可以改下为feign调用形式

RestTemplate的操作后面可以改下为feign调用形式,后面会陆续更新

image.png

临时实例和保护阙值

临时和持久实例

# 表示持久化实例
spring.cloud.nacos.discovery.ephemeral=false
  1. 默认情况Nacos中都是临时实例,可以指定配置,在注册的时候表示持久实例
  2. 客户端每隔5s向nacos发送一次心跳
  3. nacos如果超过15s没有收到客户端心跳,会把实例标记不健康
  4. 超过30s没有收到心跳,就会删除实例
  5. 持久化就是不会删除实例

保护阙值

image.png

在0-1范围指定一个比例

如果不健康的服务占比超过比例

那么该服务的所有实例都不可访问,触发保护。

保护阙值
在使用过程中,我们可以设置一个0-1的一个比例,表示如果服务的所有实例中,健康实例的比重低于这个比重就会触发保护,一旦触发保护,在服务消费端侧就会把所有实例拉取下来,不管是否健康,这样就起到了保护的作用,因为正常来说消费端只会拿到健康实例,但是如果健康实例占总实例比例比较小了,那么就会导致所有流量都会压到健康实例上,这样仅剩的几个健康实例也会被压垮,所以只要触发了保护,消费端就会拉取到所有实例,这样部分消费端仍然会访问到不健康的实例从而请求失败,但是也有一部分请求能访问到健康实例,达到保护的作用。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值