1. 首页 > 知识 > 技术

Nacos新手详细知识大全

一、Nacos快速入门

1.1 服务注册到Nacos

1.1.1 配置

**引入com.alibaba.cloud,**以后的版本就不用操心了

<!-- com.alibaba.cloud-->
            <!-- com.alibaba.cloud-->
  
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.2.6.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

nacos的管理依赖

<!--nacos的管理依赖 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-dependencies</artifactId>
    <version>2.2.5.RELEASE</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

注释掉order-service和user-service中原有的eureka依赖

添加nacos客户端依赖

在user-service及order-service中添加

服务注册发现的客户端依赖,一个启动器starter

<!-- nacos客户端依赖 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

修改user-service&order-service中的application.yml文件,注释eureka地址,添加nacos地址

spring:
  application:
    name: orderservice
  cloud:
    nacos:
    #nacos服务端地址,默认就是8848
    server-addr: localhost:8848

启动nacos

1.png

我们点击服务对应的“详情”,可以准确的看到IP和端口号

2.png


二、服务多级存储模型

2.1 服务多级存储模型

多级:

  • 一级服务(userservice)

  • 二级集群(HZ或SH)

  • 三级实例(例如杭州机房的某台部署了user vice的服务器)

假如我们将服务的实例都部署到一个机房,若出现意外,那我们的服务将会挂掉

我们会将一个服务的多个实例部署到多个机房,这样某个机房挂掉之后还能继续使用,如此做法叫做容灾

而我们nacos服务分级存储模型就引入了这样一个机房的概念,把同在一个机房的多个实例称为一个集群

3.png

服务调用尽可能选择本地集群服务,跨集群调用延迟较高

本地集群不可访问,再去访问其它集群

nacos引入集群这个概念,就是为了防止出现跨集群调用

4.png

我们可以看一下我们刚刚发布的“orderservice”是一个什么集群

由下图可看出是一个DEFAULT集群,默认集群也就是没有集群

5.png

2.2 配置实例集群属性

**修改application.yml,添加如下内容,**比之前多了discovery

spring:
  applicaiton: 
    name: userservice  
  cloud:
    nacos:
      server-addr: localhost:8848 # nacos 服务端地址
      discovery:
        cluster-name: HZ # 配置集群名称,也就是机房位置,例如:HZ,杭州

启动两个userservice,那这两个userservice就是杭州集群了

6.png

那如果我想将同样的服务在再配置到上海集群呢?

复制一个user-service服务,将cluster-name修改为cluster-name: SH,然后进行启动

注意!!!这个时候不要再启动UserApplication和UserApplication2,否则将两个服务一会去SH集群

如下图所示,HZ集群,SH集群

7.png

三、NacosRule负载均衡

3.1 初了解

我们要达到的效果:order-service远程调用user-service的时候优先调用本地集群

我们还要给order-service配置一个集群属性,相当于将order-service加入到杭州集群,我们要看一看是否会先调用本地集群

此时order-service与8081、8082在相同的集群

spring:
  application:
    name: orderservice
  cloud:
  	nacos:
      server-addr: localhost:8848
      discovery:
        cluster-name: HZ #集群名称

8.png

9.png

当我们多次访问之后,发现8081、8082、8083都会被访问,并没有优先选择同集群的8081、8082。依旧是轮询

3.2 修改负载均衡规则

在order-service中设置负载均衡的IRule为NacosRule,这个规则优先会寻找与自己同集群的服务

#要做配置的微服务名称
userservice:
  ribbon:
    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule

我们在order-service配置文件中修改之后再访问,发现8081,8082会有响应,而8083没有响应

假如我们把8081,8082都停掉(本地集群已经没有服务了)只留下在上海的8083,此时再发请求,依然会有响应, 原因是8083接收的请求并处理的

3.3 NacosRule负载均衡策略

  • 优先选择同集群服务实例列表

  • 本地集群找不到提供者,才去其他集群寻找,并且会报警告

  • 确定了可用实例列表后,再采用随即负载均衡挑选实例

四、服务实例的权重设置

场景:

服务器设备性能有差异,部分实例所在机器性能较好,另一些较差,我们希望性能好的机器承担更多的用户请求

Nacos提供了权重配置来控制访问频率,权重越大则访问频率越高权重设置为0则完全不会被访问

作用:

我们将8081,8082,8083其中的某一个停掉,用户也不会有感知。我们可以将停掉的进行版本升级,升级完成之后再进行重启(重启的时候权重不会调的很高),让少数的用户访问,以此来做测试,如果没什么问题就可以扩大权重,顺滑升级,不用半夜加班处理

权重值为0~1,权重越大则访问频率越高,权重设置为0则完全不会被访问

10.png

11.png

我在这里修改权重的时候出现了一个错误:

caused: errCode: 500, errMsg: do metadata operation failed ;caused: com.alibaba.nacos.consistency.exception.ConsistencyException: The Raft Group [naming_instance_metadata] did not find the Leader node;caused: The Raft Group [naming_instance_metadata] did not find the Leader node;

经过查找, https://www.cnblogs.com/whl-jx911/p/16736625.html这篇文章可以充分的结局上面的问题

找到nacos根目录下的data文件,删除里面的protocol文件夹

原因:Nacos 采用 raft 算法来计算 Leader,并且会记录上次启动的集群地址,所以当我们自己的服务器 IP 改变时(网络环境不稳定,如WIFI, IP 地址也经常变化),导致 raft 记录的集群地址失效,导致选 Leader 出现问题。

原因:有小伙伴,部署的nacos包,是本机运行过的,直接扔到服务器了(带着data目录),所以ip 与服务器ip不一致,导致了以上问题。

成功后如下图所示:此时8082被访问到的概率就是8081的十分之一

12.png


五、namespace命名空间环境隔离

nacos不仅是一个注册中心,也是一个数据中心

Nacos中服务存储和数据存储的最外层都是一个名为namespace的东西,用来做最外层隔离(对服务做隔离)

将来不同命名空间的服务是不能互相访问的

同个命名空间中的多个东西还可以分组Group

13.png

5.1 创建命名空间

14.png

15.png

下面是圈起来的地方是命名空间的ID

16.png

5.2 修改application.yaml添加namespace

修改order-service的application.yml,添加namespace:

spring:
  application:
    name: orderservice
      cloud:
        nacos:
          server-addr: localhost:8848
          discovery:
            cluster-name: HZ #集群名称
            namespace: 1ebcface-cc3a-4e77-96d8-2f3f0500c317 #命名空间   dev环境

命名空间ID可以从下面进行复制

17.png


5.3 环境隔离的效果

配置完成之后重启order-service,目前只有order-service在dev环境,其他都没有修改

我们看到下图中public命名空间中已经没有了orderservice服务了

18.png

但是我们查看dev服务,发现里面有orderservice服务

19.png

如果此时我们再用8080向其他三个userservice发起请求,则会报错

20.png

不同环境空间下的服务不能互相访问

不同环境空间下的服务不能互相访问

5.4 总结

  • 每个namespace都有唯一id

  • 服务设置namespace时要写id而不是名称

  • 不同namespace下的服务互相不可见,访问不到的


六、Nacos和Eureka对比

6.1 相同部分

对于Nacos

我们的服务提供者在启动时,都会把自己的信息提交给注册中心,而注册中心就会把这些信息保留下来

对于服务的消费者就可以找注册中心要这个服务信息,成为服务拉取或服务发现。服务消费者并不是每次发起请求都会去注册中心拉取。而是在拉取时将拉取到的服务信息缓存到列表中,接下来的一段时间就都可以不用拉取,而是直接使用列表中的缓存即可(这个列表会每隔30秒重新拉取并缓存)

消费者拿到服务列表之后,再经过负载均衡挑选一个发起远程调用

以上Nacos和Eureka是相同的

6.2 服务提供者不同的部分

它们两者的差别在于服务提供者的健康检测,nacos会把我们的服务提供者划分为临时实例和非临时实例

默认情况下所有的实例都是临时实例,临时实例和非临时实例在做健康检测的时候时不一样的

21.png

**临时实例:**临时的,将来我们可以人为的将他停掉所以在nacos做检查的时候采用的时心跳检测(与Eureka的心跳检测完全一致,每隔一段时间发一个请求到nacos,有一天不跳了,nacos就会将他从服务列表中剔除)

**非临时实例:**不会要求心跳检测,是由nacos主动发请求询问,并且nacos不会把非临时实例从列表中剔除,仅仅标记为不健康并且等着他恢复健康

6.3 服务消费者不同的部分

服务消费者也与Eureka有所差别

如果服务提供者在定时拉取服务之前已经挂掉了,那服务消费者在这一段时间内没有更新服务列表缓存(更新不够及时),岂不是一直调用的挂掉的服务?

答案并不是这个样子的

Eureka采用的时pull,Nacos采用的时pull+push

nacos做了一个消息推送,当nacos发现有服务挂掉,会立即发消息推送给服务消费者,服务消费者会迅速更新

6.4 图示

22.png

6.5 设置临时实例和非临时实例

spring:
  cloud:
    nacos:
      discovery:
        ephemeral: false # 设置为非临时实例

6.6 总结

6.6.1 相同

  • 都支持服务注册和服务拉取

  • 都支持服务提供者心跳方式做健康检测

6.6.2 不同

  • Nacos支持服务端主动检测提供者状态:临时实例采用心跳模式,非临时实例采用主动检测模式(推荐使用临时实例)

  • 临时实例心跳不正常会被剔除,非临时实例则不会被剔除

  • Nacos支持服务列表变更的消息推送模式,服务列表更新更及时

  • Nacos集群默认采用AP方式,当集群中存在非临时实例时,采用CP模式;Eureka采用AP方式

七、配置管理

**实现配置热更新:**一般我们更改配置文件后需要再启动工程才能得以使用,但是一般工程启动时间较长,这样做的话效率很低(还有就是一个配置文件的内容好几个微服务都相同),如今我们可以利用Nacos实现配置统一管理,这些配置就会立马能够生效

配置管理服务: 会记录微服务中一些核心的配置放到上面去,微服务启动的时候就会读取配置管理服务上的配置,再与本地的配置结合,就可以完整的使用。我们之后修改配置就直接再配置管理中修改,配置管理发现配置改动后会立刻通知响应的微服务,微服务可以实现配置热更新并不需要重启服务

配置管理与注册中心都是由Nacos实现的

23.png

7.1 新建配置

24.png

创建的时候DataID要唯一,不能冲突,为了保证不冲突,我们可以用微服务名(微服务名不冲突)

DataId一般格式: 微服务名称-profile.yaml

profile指的是当前项目的运行环境,如dev,test,prod,根据自己的需求定即可

Group:分组,确定这个配置在哪个组里面

配置格式:一般选择YAML

配置内容:不需要把所有的配置都复制到这里来,我们只需要一些开关类型的数据、模板类的数据,简单的来说就是需要热更新配置的

25.png

如下图所示,创建配置成功,也完成了配置统一管理

26.png

7.2 微服务拉取配置

我们的项目会把nacos配置文件中的配置与本地配置做一个合并,再去做后面的动作

所以我们要先读取nacos配置文件,那怎么先读取nacos配置文件呢?

创建bootstrap.yml配置文件,优先级比application.yml配置文件高,会优先读取

27.png

7.2.1 Nacos的配置管理客户端依赖

优先级比application.yml配置文件高,会优先读取

nacos-config表示管理配置 如果是nacos-discovery则表示服务发现

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

7.2.2 resource目录下添加bootstrap.yml文件

在user-service工程的resource目录下添加bootstrap.yml

name、active、file-extension决定了我们的DataID

spring:
  application:
    name: userservice # 服务名称
  profiles:
    active: dev #开发环境,这里是dev
  cloud:
    nacos:
      server-addr: localhost:8848 # Nacos地址
      config:
        file-extension: yaml # 文件后缀名

7.2.3 读取配置

 //  从nacos远程获取配置
    @Value("${pattern.dateformat}")
    private String dateformat;
 
    @GetMapping("/now")
    public String now() {
//      LocalDateTime工具类
//      LocalDateTime.now()获取当前时间
//      format(DateTimeFormatter.ofPattern(dateformat)格式化
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(dateformat));
    }

28.png

7.3 总结

将配置交给Nacos管理的步骤

  • 在Nacos中添加配置文件

  • 在微服务中引入nacos的config依赖

  • 在微服务中添加bootstrap.yml,配置nacos地址、当前环境、服务名称、文件后缀名。这些决定了程序启动时去nacos读取哪个文件

八、实现配置热更新

配置热更新就是我们的最终目标


8.1 方式一:注解@RefreshScope

在@Value注入的变量所在类上添加注解@RefreshScope

 @Slf4j
@RestController
@RequestMapping("/user")
@RefreshScope
public class UserController {
}

我们先更改一下配置

29.png

将新的配置发布之后,我们不用重启微服务就可以读取到上面的新配置并且控制台还会有提示

30.png


8.2 方式二:@ConfigurationProperties注解


推荐使用@ConfigurationProperties注解,完成配置自动加载

新建一个类专门完成属性的加载

 @Data
@Component   //注册成一个bean
//prefix 前缀   只要前缀名和属性名拼接(即pattern.dateformat)能和nacos配置管理中的配置(pattern.dateformat)对应即可
@ConfigurationProperties(prefix = "pattern")
public class PatternProperties {
//  希望dateformat属性和配置文件一致
    private String dateformat;
}
 
    @Autowired
    private PatternProperties properties;
 
    @GetMapping("/now")
    public String now() {
//      LocalDateTime工具类
//      LocalDateTime.now()获取当前时间
//      format(DateTimeFormatter.ofPattern(dateformat)格式化
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(properties.getDateformat()));
    }

31.png

32.png

33.png

8.3 总结

Nacos配置更改后,微服务可以实现热更新,方式:

  • 通过@Value注解注入,结合@RefreshScope来刷新

  • 通过@ConfigurationProperties注入,自动刷新

注意事项:

  • 不是所有的配置都适合放到配置中心,维护起来比较麻烦

  • 建议将一些关键参数,需要运行时调整的参数放到nacos配置中心,一般都是自定义配置


九、多环境配置共享

某一个配置属性,在开发、生产、测试等环境下的值时一样的,如果在每个配置文件中都写一份,就会有些浪费,而且改的时候都要改

为了针对这种情况,我们希望配置一次之后,不管环境怎么改变,这个配置都能够被加载,这就是多环境共享的一个需求了。

微服务启动时会从nacos读取多个配置文件:

  • [spring.application.name]-[spring.profiles.active].yaml,例如:userservice-dev.yaml

  • [spring.application.name].yaml,例如:userservice.yaml,服务名直接跟上后缀,把环境省略掉,和环境并没有关系

对于第二种,无论profile如何变化,[spring.application.name].yaml这个文件一定会加载,因此多环境共享配置可以写入这个文件

9.1创建多环境配置

34.png

35.png

9.2 修改共享配置文件的属性

比之前多了envSharedValue

 @Data
@Component   //注册成一个bean
//prefix 前缀   只要前缀名和属性名拼接(即pattern.dateformat)能和nacos配置管理中的配置(pattern.dateformat)对应即可
@ConfigurationProperties(prefix = "pattern")
public class PatternProperties {
//  希望dateformat属性和配置文件一致
    private String dateformat;
 
//  再读一个环境共享属性
    private String envSharedValue;
 
}
 
    @GetMapping("prop")
    public PatternProperties properties(){
//       直接将这个返回,那页面就能看到这个类中的所有东西了
         return  properties;
    }

配置完成后重启userapplication,并且其在dev环境

此时userservice(8081)工程能读到dev环境下的配置(userservice-dev.yaml),也能读取到共享配置文件的内容(userservice.yaml)

为了做对比,我们再启动一个userservice服务(8082),并且设置成test环境

36.png

也可以采用下面这个方式,推荐,因为上面那个方式修改之后还要改回来

37.png


9.3 验证结果

我们发现8081端口都可以读取到

38.png

而8082端口只能读取到环境共享属性值

39.png


dev环境8081,test环境8082都能拿到userservice.yaml文件的配置,证明此文件是被不同环境共享的

9.4 配置文件优先级问题

[服务名]-[环境].yaml >[服务名].yaml > 本地配置

40.png

本地配置的优先级最低,nacos中环境配置最高


9.5 多服务共享配置

不同微服务之间可以共享配置文件,通过下面的两种方式来指定:


9.5.1 方式1

spring:
  application:
    name: userservice # 服务名称
   profiles:
     active: dev # 环境,
   cloud:
     nacos:      
       server-addr: localhost:8848 # Nacos地址      
       config:         
         file-extension: yaml # 文件后缀名        
         shared-configs: # 多微服务间共享的配置列表          
           - dataId: common.yaml # 要共享的配置文件id

9.5.2 方式2

spring:
  application:
    name: userservice # 服务名称
   profiles:
     active: dev # 环境,
   cloud:
     nacos:      
       server-addr: localhost:8848 # Nacos地址      
       config:         
         file-extension: yaml # 文件后缀名        
         extends-configs: # 多微服务间共享的配置列表
            - dataId: extend.yaml # 要共享的配置文件id

十、Nacos集群搭建

10.1 集群结构图

官方给出的Nacos集群图:

41.png

SLB:负载均衡器,将请求分发到不同的Nacos节点,就形成一个集群结构了

三台Nacos节点要实现数据的共享(整个MySQL集群,让多个nacos都去访问集群完成数据的读写)

42.png


10.2 搭建集群

三个nacos节点的地址:


节点ipport
nacos1192.168.150.18845
nacos2192.168.150.18846
nacos3192.168.150.18847

搭建集群的基本步骤:

  • 搭建数据库,初始化数据库表结构

  • 下载nacos安装包

  • 配置nacos

  • 启动nacos集群

  • nginx反向代理

    10.2.1 初始化数据库


    Nacos默认数据存储在内嵌数据库Derby中,不属于生产可用的数据库。

    官方推荐的最佳实践是使用带有主从的高可用数据库集群。

    这里我们以单点的数据库为例来讲解。

    首先新建一个数据库,命名为nacos,而后导入的nacos-server带的数据库初始化文件: ${nacoshome}/conf/nacos- mysql.sql   

    可参考Nacos简介以及Nacos Server安装

    10.2.2 配置Nacos

    我们三个Nacos就要有三次配置

    目录说明:

    • bin:启动脚本

    • conf:配置文件

    进入nacos的conf目录,修改配置文件cluster.conf.example,重命名为cluster.conf:

    43.png

    添加内容,其实配置集群中每一个节点的信息

    127.0.0.1:8845
    127.0.0.1.8846
    127.0.0.1.8847

    然后修改application.properties文件

    将下面两个注释打开,db.num代表着数据库的数量

    找到数据库的配置并更改成下面的数据库配置(根据实际情况进行修改)

    spring.datasource.platform=mysql
    db.num=1
    db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
    db.user.0=root
    db.password.0=root

    10.2.3 启动

    将nacos文件夹复制三份,分别命名为:nacos1、nacos2、nacos3

    然后分别修改三个文件夹中的application.properties,

    nacos1:

    <code class="language-plaintext hljs">server.port=8845</code>

    nacos2:

    <code class="language-plaintext hljs">server.port=8846</code>

    nacos3:

    <code class="language-plaintext hljs">server.port=8847</code>

    然后分别启动三个nacos节点:

    <code class="language-plaintext hljs">startup.cmd</code>

    10.2.4 nginx反向代理

    将nginx下载并解压

    修改conf/nginx.conf文件,配置如下:

    upstream nacos-cluster {
        server 127.0.0.1:8845;
    	server 127.0.0.1:8846;
    	server 127.0.0.1:8847;
    }
     
    server {
        listen       80;
        server_name  localhost;
     
        location /nacos {
            proxy_pass http://nacos-cluster;
        }
    }

    而后在浏览器访问:http://localhost/nacos即可。

    代码中application.yml文件配置如下:

    spring:
      cloud:
        nacos:
          server-addr: localhost:80 # Nacos地址

    此时下面的nacos地址也变成了80,而不是之前的8848

    44.png


    10.2.5 优化

    • 实际部署时,需要给做反向代理的nginx服务器设置一个域名,这样后续如果有服务器迁移nacos的客户端也无需更改配置.

    • Nacos的各个节点应该部署到多个不同服务器,做好容灾和隔离


    https://nacos.io/

    Nacos新手详细知识大全


    本文由一叶发布,不代表一叶立场,转载联系作者并注明出处:https://yiyeo.com/jishu/329.html

    加载中~

    联系我们

    在线咨询:点击这里给我发消息

    微信号:

    工作日:10:30-15:30,节假日休息