Nacos详解

Nacos是什么

 

 

欢迎来到Nocos的世界!

组成部分全称描述
Na naming/nameServer 即服务注册中心,与 Spring Cloud Eureka 的功能类似。
co configuration 即配置中心,与 Spring Cloud Config+Spring Cloud Bus 的功能类似。
s service 即服务,表示 Nacos 实现的服务注册中心和配置中心都是以服务为核心的。

Nacos 是 Dynamic Naming and Configuration-Service 的首字母简称,定位于一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。从 2018 年 7 月开始宣布开源以来,已经走过了第四个年头,在这四年里,备受广大开源用户欢迎,共收获 25.1K ⭐的 star 数11.1K 的 Fork 🌲 数

Nacos 在社区共同的建设下不断成长,逐步的开始帮助用户解决实际问题,助力企业数字化转型,目前已经广泛的使用在国内的公司中。

Nacos两大组件

组件描述功能
Nacos Server Nacos 服务端,与 Eureka Server 不同,Nacos Server 由阿里巴巴团队使用 Java 语言编写并将 Nacos Server 的下载地址给用户,用户只需要直接下载并运行即可。 Nacos Server 可以作为服务注册中心,帮助 Nacos Client 实现服务的注册与发现。
Nacos Server 可以作为配置中心,帮助 Nacos Client 在不重启的情况下,实现配置的动态刷新。
Nacos Client Nacos 客户端,通常指的是微服务架构中的各个服务,由用户自己搭建,可以使用多种语言编写。 Nacos Client 通过添加依赖 spring-cloud-starter-alibaba-nacos-discovery,在服务注册中心(Nacos Server)中实现服务的注册与发现。
Nacos Client 通过添加依赖 spring-cloud-starter-alibaba-nacos-config,在配置中心(Nacos Server)中实现配置的动态刷新。

数据模型(配置和服务的组织形式)

Nacos 数据模型 Key 由三元组唯一确定。 Namespace默认是空串,公共命名空间(public)。分组默认是 DEFAULT_GROUP。

 

 

nacos相关概念

  • 命名空间(Namespace)

    Namespace 的常用场景之一是不同环境的配置的区分隔离,例如开发测试环境(dev)和生产环境(pro)的资源(如配置、服务)隔离等。

    • 可以隔离开发环境——测试环境和生产环境,因为它们的配置可能各不相同;
    • 可以隔离不同的用户——不同的开发人员使用同一个nacos管理各自的配置,可通过namespace隔离。不同的命名空间下,可以存在相同名称的配置分组(Group) 或配置集。
  • 配置分组(group)

    Nacos 中的一组配置集,一个有意义的字符串(如 Buy 或 Trade )对配置集进行分组,从而区分 Data ID 相同的配置集,默认采用 DEFAULT_GROUP 。

    配置分组的常见场景:不同的应用或组件使用了相同的配置类型,如 database_url 配置和 MQ_topic 配置。

  • 配置集/配置集ID(Service/DataId)

    配置项的集合称为配置集。在系统中,一个配置文件通常就是一个配置集,包含了系统各个方面的配置。每个配置集都可以被一个有意义的名称标识——配置集 ID (Data ID)。

其他相关概念详情请阅读官网Nacos 概念

安装和下载Nacos服务

下面我们以 Nacos 2.0.3 为例,演示下如何安装和运行 Nacos Server,步骤如下。

  1. 使用浏览器访问 Nacos Server 下载页面,并在页面最下方点击链接 nacos-server-2.0.3.zip,如下图。

     

     

     

  2. 下载完成后,解压 nacos-server-2.0.3.zip,目录结构如下。

     

     

     

  3. 打开命令行窗口,跳转到 Nacos Server 安装目录的 bin 下,执行以下命令,以单机模式启动 Nacos Server。

     
     
     
     
     
     
    # 单机模式
    startup.cmd -m standalone
     

     

  4. Nacos Server 启动日志如下。

     
     
     
     
     
     
    "nacos is starting with standalone"
    
    
             ,--.
           ,--.'|
       ,--,:  : |                                           Nacos 2.0.3
    ,`--.'`|  ' :                       ,---.               Running in stand alone mode, All function modules
    |   :  :  | |                      '   ,'\   .--.--.    Port: 8848
    :   |   \ | :  ,--.--.     ,---.  /   /   | /  /    '   Pid: 27512
    |   : '  '; | /       \   /     \.   ; ,. :|  :  /`./   Console: http://192.168.3.138:8848/nacos/index.html
    '   ' ;.    ;.--.  .-. | /    / ''   | |: :|  :  ;_
    |   | | \   | \__\/: . ..    ' / '   | .; : \  \    `.      https://nacos.io
    '   : |  ; .' ," .--.; |'   ; :__|   :    |  `----.   \
    |   | '`--'  /  /  ,.  |'   | '.'|\   \  /  /  /`--'  /
    '   : |     ;  :   .'   \   :    : `----'  '--'.     /
    ;   |.'     |  ,     .-./\   \  /            `--'---'
    '---'        `--`---'     `----'
    
    
    2021-11-08 16:16:38,877 INFO Bean 'org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler@5ab9b447' of type [org.springframework.security.access.expression.method
    .DefaultMethodSecurityExpressionHandler] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2021-11-08 16:16:38,884 INFO Bean 'methodSecurityMetadataSource' of type [org.springframework.security.access.method.DelegatingMethodSecurityMetadataSource] is not eligible for getting processed by al
    l BeanPostProcessors (for example: not eligible for auto-proxying)
    2021-11-08 16:16:40,001 INFO Tomcat initialized with port(s): 8848 (http)
    2021-11-08 16:16:40,713 INFO Root WebApplicationContext: initialization completed in 14868 ms
    2021-11-08 16:16:52,351 INFO Initializing ExecutorService 'applicationTaskExecutor'
    2021-11-08 16:16:52,560 INFO Adding welcome page: class path resource [static/index.html]
    2021-11-08 16:16:54,239 INFO Creating filter chain: Ant [pattern='/**'], []
    2021-11-08 16:16:54,344 INFO Creating filter chain: any request, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@7dd611c8, org.springframework.security.web.con
    text.SecurityContextPersistenceFilter@5c7668ba, org.springframework.security.web.header.HeaderWriterFilter@fb713e7, org.springframework.security.web.csrf.CsrfFilter@6ec7bce0, org.springframework.secur
    ity.web.authentication.logout.LogoutFilter@7d9ba6c, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@158f4cfe, org.springframework.security.web.servletapi.SecurityContextHolderAwa
    reRequestFilter@6c6333cd, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@5d425813, org.springframework.security.web.session.SessionManagementFilter@13741d5a, org.springf
    ramework.security.web.access.ExceptionTranslationFilter@3727f0ee]
    2021-11-08 16:16:54,948 INFO Initializing ExecutorService 'taskScheduler'
    2021-11-08 16:16:54,977 INFO Exposing 16 endpoint(s) beneath base path '/actuator'
    2021-11-08 16:16:55,309 INFO Tomcat started on port(s): 8848 (http) with context path '/nacos'
    2021-11-08 16:16:55,319 INFO Nacos started successfully in stand alone mode. use embedded storage
     

     

  5. 使用浏览器访问“http://localhost:8848/nacos”,跳转到 Nacos Server 登陆页面,如下图。

     

     

     

  6. 在登陆页输入登录名和密码(默认都是 nacos),点击提交按钮,跳转到 Nacos Server 控制台主页,如下图。

     

     

     

    自此,我们就完成了 Nacos Server 的下载、安装和运行工作。

 

Nacos server集群部署

在实际的项目开发中,一个微服务系统往往由十几,几十个甚至几百个微服务组成。 这些服务若全部注册到同一台 Nacos Server,就极有可能导致 Nacos Server 因为不堪重负而崩溃,最终导致整个微服务系统瘫痪。解决这个问题最直接的办法就是使用 Nacos Server 集群。

Nacos Server 的集群化部署有一个十分明显的优点,那就是可以保障系统的高可用性。在集群化部署中,只要不是所有的 Nacos Server 都停止工作,Nacos Client 就还可以从集群中正常的 Nacos Server 上获取服务信息及配置,而不会导致系统的整体瘫痪,这就是 Nacos Server 集群化部署的高可用性。

下图展示了 Nacos Server 集群化部署的基本架构。

 

 

下面我们以 Windows 系统为例,演示如何部署 Nacos Server 集群。

  1. 复制三分Nacos目录分别修改application.properties的端口号为8848、8846、8844

  2. 在conf目录下新建cluster.conf 输入:

     
     
     
     
     
     
    192.168.10.76:8845
    192.168.10.76:8847
    192.168.10.76:8849
     
  3. 启动nginx.exe, nginx的配置文件如下:

     
     
     
     
     
     
    http {
        upstream nacos {
                    server 192.168.10.76:8848;
                    server 192.168.10.76:8846;
                    server 192.168.10.76:8844;
            }
            server {
                listen       80;
                server_name  localhost;
    
    
                #charset koi8-r;
    
    
                #access_log  logs/host.access.log  main;
    
    
                location / {
                    root   html;
                    index  index.html index.htm;
                    add_header Access-Control-Allow-Origin *;
                }
    
    
                location /nacos/ {
                    proxy_pass http://nacos/nacos/;
                }
          }
    }
     

     

  4. 分别打开三个nacos的bin目录,执行下面命令:

     
     
     
     
     
     
    startup.cmd -m cluster
     

     

  5. 启动日志如下:

     
     
     
     
     
     
    "nacos is starting with cluster"
    
    
             ,--.
           ,--.'|
       ,--,:  : |                                           Nacos 2.1.1
    ,`--.'`|  ' :                       ,---.               Running in cluster mode, All function modules
    |   :  :  | |                      '   ,'\   .--.--.    Port: 8848
    :   |   \ | :  ,--.--.     ,---.  /   /   | /  /    '   Pid: 16340
    |   : '  '; | /       \   /     \.   ; ,. :|  :  /`./   Console: http://192.168.10.76:8848/nacos/index.html
    '   ' ;.    ;.--.  .-. | /    / ''   | |: :|  :  ;_
    |   | | \   | \__\/: . ..    ' / '   | .; : \  \    `.      https://nacos.io
    '   : |  ; .' ," .--.; |'   ; :__|   :    |  `----.   \
    |   | '`--'  /  /  ,.  |'   | '.'|\   \  /  /  /`--'  /
    '   : |     ;  :   .'   \   :    : `----'  '--'.     /
    ;   |.'     |  ,     .-./\   \  /            `--'---'
    '---'        `--`---'     `----'
    
    
    2023-01-03 16:14:49,041 INFO The server IP list of Nacos is [192.168.10.76:8844, 192.168.10.76:8846, 192.168.10.76:8848]
    
    
    2023-01-03 16:14:50,042 INFO Nacos is starting...
    
    
    2023-01-03 16:14:51,043 INFO Nacos is starting...
    
    
    2023-01-03 16:14:52,062 INFO Nacos is starting...
    
    
    2023-01-03 16:14:53,080 INFO Nacos is starting...
    
    
    2023-01-03 16:14:54,085 INFO Nacos is starting...
    
    
    2023-01-03 16:14:55,086 INFO Nacos is starting...
    
    
    2023-01-03 16:14:56,089 INFO Nacos is starting...
    
    
    2023-01-03 16:14:57,091 INFO Nacos is starting...
    
    
    2023-01-03 16:14:58,094 INFO Nacos is starting...
    
    
    2023-01-03 16:14:58,799 INFO Nacos started successfully in cluster mode. use external storage
     

     

  6. 访问http://localhost/nacos,在页面的集群管理下的节点列表中可以看到如下启动节点,则说明启动成功,页面如下:

     

     

  7. 将主工程配置文件中的 Nacos Server 地址统一修改为:localhost:80。我们以 spring-cloud-alibaba-consumer-nacos-8801 为例,配置文件 application.yml 的配置内容如下。

Spring Boot集成Nacos

启动配置管理

1. 添加依赖

 
 
 
 
 
 
<dependency>
    <groupId>com.alibaba.boot</groupId>
    <artifactId>nacos-config-spring-boot-starter</artifactId>
    <version>0.2.8</version>
</dependency>
 

2. 在 application.properties 中配置 Nacos server 的地址

 
 
 
 
 
 
nacos.config.server-addr=127.0.0.1:8848
 

3. 配置加载获取

  • 使用 @NacosPropertySource 加载 dataIdexample 的配置文件,并开启自动更新

     
     
     
     
     
     
    @SpringBootApplication
    @NacosPropertySource(dataId = "example", autoRefreshed = true)
    public class NacosExampleApplication {
        public static void main(String[] args) {
            SpringApplication.run(NacosExampleApplication.class, args);
        }
    }
     
  • 通过 Nacos 的 @NacosValue 注解设置属性值

     
     
     
     
     
     
    @Controller
    @RequestMapping("config")
    public class ConfigController {
     @NacosValue(value = "${useLocalCache:false}", autoRefreshed = true)
     private boolean useLocalCache;
    
    
     @RequestMapping(value = "/get", method = GET)
     @ResponseBody
     public boolean get() {
         return useLocalCache;
     }
    }
     

启动服务发现

1. 添加依赖

 
 
 
 
 
 
<dependency>
    <groupId>com.alibaba.boot</groupId>
    <artifactId>nacos-discovery-spring-boot-starter</artifactId>
    <version>0.2.8</version>
</dependency>
 

2. 在 application.properties 中配置 Nacos server 的地址

 
 
 
 
 
 
nacos.config.server-addr=127.0.0.1:8848
 

3. 服务发现

  • 编写测试接口并启动 NacosExampleApplication

     
     
     
     
     
     
    @Controller
    @RequestMapping("discovery")
    public class DiscoveryController {
    
    
        @NacosInjected
        private NamingService namingService;
    
    
        @RequestMapping(value = "/get", method = GET)
        @ResponseBody
        public List<Instance> get(@RequestParam String serviceName) throws NacosException {
            return namingService.getAllInstances(serviceName);
        }
    }
     
  • 访问 curl http://localhost:8080/discovery/get?serviceName=example,返回内容为:

     
     
     
     
     
     
    [
        {
            "instanceId": "127.0.0.1#8080#DEFAULT#DEFAULT_GROUP@@example",
            "ip": "127.0.0.1",
            "port": 8080,
            "weight": 1.0,
            "healthy": true,
            "enabled": true,
            "ephemeral": true,
            "clusterName": "DEFAULT",
            "serviceName": "DEFAULT_GROUP@@example",
            "metadata": {},
            "instanceHeartBeatInterval": 5000,
            "instanceHeartBeatTimeOut": 15000,
            "ipDeleteTimeout": 30000,
            "instanceIdGenerator": "simple"
        }
    ]
     

Spring Cloud集成Nacos

  1. 在pom文件中引入依赖

     
     
     
     
     
     
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    </dependency>
     

     

  2. 在bootstrap.yml中配置Nacos Server地址

     
     
     
     
     
     
    spring:
      application:
        name: nacos_demo
      cloud:
        nacos:
          config:
            server-addr: 127.0.0.1:8848
            group: DEFAULT_GROUP
            file-extension: yaml
            namespace: public
            name: nacos_demo
          discovery:
            server-addr: 127.0.0.1:8848
            namespace: public
            group: DEFAULT_GROUP
     

     

  3. 在主启动类上添加@EnableDiscoveryClient注解来开启注册客户端

     
     
     
     
     
     
    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableConfigurationProperties
    public class DemoApplication {
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class, args);
        }
    }
    
    
     
  4. 启动Nacos Server客户端 创建Data Id 为nacos_demo的配置文件

Q&A

Nacos 和Eureka有什么优势

  • 功能差异

模块NacosEureka说明
注册中心 服务治理基本功能,负责服务中心化注册
配置中心 Eureka需要配合Config实现配置中心,且不提供管理界面
动态刷新 Eureka需要配合MQ实现配置动态刷新,Nacos采用Netty保持TCP长连接实时推送
可用区AZ 对服务集群划分不同区域,实现区域隔离,并提供容灾自动切换
分组 Nacos可用根据业务和环境进行分组管理
元数据 提供服务标签数据,例如环境或服务标识
权重 Nacos默认提供权重设置功能,调整承载流量压力
健康检查 Nacos支持由客户端或服务端发起的健康检查,Eureka是由客户端发起心跳
负载均衡 均提供负责均衡策略,Eureka采用Ribion
管理界面 Nacos支持对服务在线管理,Eureka只是预览服务状态
  • 部署安装

模块NacosEureka说明
MySql Nacos需要采用MySql进行数据进行持久化
MQ Eureka需要采用MQ进行配置中心刷新
配置中心 Eureka结合Config或者Consul实现配置中心
配置文件 在线编辑 本地文件或者Git远程文件 Eureka结合Config或者Consul
集群 Nacos需要配置集群ip再启动

大部分不适用Eureka的原因是因为2.x闭源了

Nacos 端口占用说明

集群配置中不要使用连续端口,nacos 2.0之后增加了默认的服务端口供nacos内部使用

对于Nacos2.x客户端来说,默认的9848也是根据当前客户端指定的8848端计算指定的,所以当更改服务端8848端口以后,建议提前计算好对应的GRPC端口。

端口含义
8848 Nacos项目核心启动主端口,HTTP服务接口
9848 Nacos中的GRPC SDK Server端的端口,用于客户端GRPC连接,默认为主端口偏移+1000
9849 Nacos中的GRPC Cluster Server端的端口,用于集群机器间,GRPC同步通信,默认为主端口偏移+1001
7848 Nacos中的Raft数据同步端口,用于服务端集群之间数据同步,默认为主端口偏移-1000
 
 
 
 
 
 
public static final Integer SDK_GRPC_PORT_DEFAULT_OFFSET = 1000;
public static final Integer CLUSTER_GRPC_PORT_DEFAULT_OFFSET = 1001; 
private static final int DEFAULT_RAFT_OFFSET_PORT = 1000;
 

 

动态刷新配置

  1. 通过 Spring Cloud 原生注解 @RefreshScope 实现配置自动更新:

     
     
     
     
     
     
    @RestController
    @RefreshScope
    @RequiredArgsConstructor
    public class NacosTestController {
        @Value("${server.port}")
        private String port;
        @Value("${user.age}")
        private String age;
    
    
        @RequestMapping("refreshScope")
        public Map<String, Object> refreshScope() {
            final HashMap<String, Object> map = new HashMap<>(12);
            map.put("port", port);
            map.put("age", age);
            return map;
        }
    }
     
  2. @ConfigurationProperties 注解修饰的配置类:这些配置类生效的原因是触发了 EnvironmentChangeEvent 事件

     
     
     
     
     
     
    @Setter
    @ToString
    @Configuration
    @ConfigurationProperties("user")
    public class User {
        /**
         * 姓名
         */
        private String name;
        /**
         * 昵称
         */
        private String nickName;
        /**
         * 年龄
         */
        private Long age;
        /**
         * 性别
         */
        private String sex;
    }
     
  3. 通过 Environment 获取的配置:例如 env.getProperty("book.category")

     
     
     
     
     
     
    final private Environment environment;
    
    
    @RequestMapping("getProperty")
    public String getProperty(String property) {
        return property + ":" + environment.getProperty(property);
    }
    
    
     

版本说明

由于 Spring Boot 3.0,Spring Boot 2.7~2.4 和 2.4 以下版本之间变化较大,目前企业级客户老项目相关 Spring Boot 版本仍停留在 Spring Boot 2.4 以下,为了同时满足存量用户和新用户不同需求,社区以 Spring Boot 3.0 和 2.4 分别为分界线,同时维护 2022.x、2021.x、2.2.x 三个分支迭代。 为了规避相关构建过程中的依赖冲突问题,我们建议可以通过 云原生应用脚手架 进行项目创建。

2022.x 分支

适配 Spring Boot 3.0,Spring Cloud 2022.x 版本及以上的 Spring Cloud Alibaba 版本按从新到旧排列如下表(最新版本用*标记): (注意,该分支 Spring Cloud Alibaba 版本命名方式进行了调整,未来将对应 Spring Cloud 版本,前三位为 Spring Cloud 版本,最后一位为扩展版本,比如适配 Spring Cloud 2022.0.0 版本对应的 Spring Cloud Alibaba 第一个版本为:2022.0.0.0,第个二版本为:2022.0.0.1,依此类推)

Spring Cloud Alibaba VersionSpring Cloud VersionSpring Boot Version
2022.0.0.0-RC* Spring Cloud 2022.0.0 3.0.0

2021.x 分支

适配 Spring Boot 2.4,Spring Cloud 2021.x 版本及以上的 Spring Cloud Alibaba 版本按从新到旧排列如下表(最新版本用*标记):

Spring Cloud Alibaba VersionSpring Cloud VersionSpring Boot Version
2021.0.4.0* Spring Cloud 2021.0.4 2.6.11
2021.0.1.0 Spring Cloud 2021.0.1 2.6.3
2021.1 Spring Cloud 2020.0.1 2.4.2

2.2.x 分支

适配 Spring Boot 为 2.4,Spring Cloud Hoxton 版本及以下的 Spring Cloud Alibaba 版本按从新到旧排列如下表(最新版本用*标记):

Spring Cloud Alibaba VersionSpring Cloud VersionSpring Boot Version
2.2.9.RELEASE* Spring Cloud Hoxton.SR12 2.3.12.RELEASE
2.2.8.RELEASE Spring Cloud Hoxton.SR12 2.3.12.RELEASE
2.2.7.RELEASE Spring Cloud Hoxton.SR12 2.3.12.RELEASE
2.2.6.RELEASE Spring Cloud Hoxton.SR9 2.3.2.RELEASE
2.2.1.RELEASE Spring Cloud Hoxton.SR3 2.2.5.RELEASE
2.2.0.RELEASE Spring Cloud Hoxton.RELEASE 2.2.X.RELEASE
2.1.4.RELEASE Spring Cloud Greenwich.SR6 2.1.13.RELEASE
2.1.2.RELEASE Spring Cloud Greenwich 2.1.X.RELEASE
2.0.4.RELEASE(停止维护,建议升级) Spring Cloud Finchley 2.0.X.RELEASE
1.5.1.RELEASE(停止维护,建议升级) Spring Cloud Edgware 1.5.X.RELEASE

组件版本关系

每个 Spring Cloud Alibaba 版本及其自身所适配的各组件对应版本如下表所示(注意,Spring Cloud Dubbo 从 2021.0.1.0 起已被移除出主干,不再随主干演进):

Spring Cloud Alibaba VersionSentinel VersionNacos VersionRocketMQ VersionDubbo VersionSeata Version
2022.0.0.0-RC 1.8.6 2.2.1-RC 4.9.4 ~ 1.6.1
2.2.9.RELEASE 1.8.5 2.1.0 4.9.4 ~ 1.5.2
2021.0.4.0 1.8.5 2.0.4 4.9.4 ~ 1.5.2
2.2.8.RELEASE 1.8.4 2.1.0 4.9.3 ~ 1.5.1
2021.0.1.0 1.8.3 1.4.2 4.9.2 ~ 1.4.2
2.2.7.RELEASE 1.8.1 2.0.3 4.6.1 2.7.13 1.3.0
2.2.6.RELEASE 1.8.1 1.4.2 4.4.0 2.7.8 1.3.0
2021.1 or 2.2.5.RELEASE or 2.1.4.RELEASE or 2.0.4.RELEASE 1.8.0 1.4.1 4.4.0 2.7.8 1.3.0
2.2.3.RELEASE or 2.1.3.RELEASE or 2.0.3.RELEASE 1.8.0 1.3.3 4.4.0 2.7.8 1.3.0
2.2.1.RELEASE or 2.1.2.RELEASE or 2.0.2.RELEASE 1.7.1 1.2.1 4.4.0 2.7.6 1.2.0
2.2.0.RELEASE 1.7.1 1.1.4 4.4.0 2.7.4.1 1.0.0
2.1.1.RELEASE or 2.0.1.RELEASE or 1.5.1.RELEASE 1.7.0 1.1.4 4.4.0 2.7.3 0.9.0
2.1.0.RELEASE or 2.0.0.RELEASE or 1.5.0.RELEASE 1.6.3 1.1.1 4.4.0 2.7.3 0.7.1

 

Nacos 版本选择

Nacos 经过 4 年的发展,目前在大版本演进上已经到了第二代 Nacos 架构,即 Nacos 2.x 版本,Nacos 2.x 版本是基于 Nacos 1.x 中用户反馈使用习惯以及产品演进方向而构建的产品能力,中间包含了比如一致性算法升级,对性能的 10 倍提升,以及支持插件化来满足社区的定制诉求。并且保障了很好的兼容性,在服务能力上 Nacos 2.x 是完全兼容 Nacos 1.x 的协议,也就是 Nacos 2.x 服务端是完全兼容 Nacos 1.x 的客户端。

 

 

 

在基本能力上,Nacos 2.x 一致性协议复用了阿里在该领域最佳实践,以长连接为基础,减低通信损耗,基于Distro协议原有协议进行升级,在存储模型、保活模型上进行了重构,并且用推送机制代替了之前的轮训机制,进一步提升了产品的高可用以及稳定性,整体也复用了阿里百万实例的基础模型,在CAP理论基础上,根据场景来去选择最适合的协议,贴合场景来平衡一致性、高可用以及分区容灾,做到服务发现以及配置管理每个场景下,都做到稳定性、高可用、高性能的保障。

 

 

 

在拓展能力上,Nacos 2.x版本开始支持插件化能力,基于插件化是更方便的支持用户各种场景,很多用户公司内部有完善的体系基于Nacos可以简单的改造就可以融合进入,在鉴权、配置加解密场景都可以做到按照用户需求进行定制,并且给出默认的开源实现供用户选择,加解密为例,开源给出的默认实现是基于AES,用户也可以进行自定义。并且目前数据库的插件已经在路上,后续还会在安全等更多方面支持可插拔的插件化能力。

 

 

 

总结版本选择:

  1. 使用Nacos2.x版本是目前Nacos的最佳选择
  2. 在1.x版本升级到2.0.4是最默认兼容平滑

Nacos的规划

Nacos 已经经历了两个重要阶段,初创期和高速发展期,目前正处于被大规模使用的 Nacos 的第三阶段是成为基础设施,需要面向于基础设施进行演进,帮助企业数字化转型,深度的拥抱各个领域内的场景,并且更深度的帮助企业解决问题。Nacos 社区目前面向于第三阶段,开始筹备 Nacos 3.0 架构设计进行规划讨论,并且逐步开始进行落地。

目前针对 Nacos 3.0 的建设规划大图主要包含三部分,第一部分是开源品牌和社区的升级,主要是面向于社区建立更紧密的联系。第二部分是面向更多生态进行深度融合,包含 K8s 数据整合、以及多生态数据打通,第三部分是最基础的部分,产品能力升级,基于 Nacos2.x 的协议进行增强,并且支持统一控制面、多数据中心等基础能力,用于支撑 Nacos 3.0 生态建设以及品牌升级。

目前 Nacos 3.0 部分已经随着社区核心贡献者开展中,大多数还在规划阶段,后续会通过 Github issues 进行开放,随之会打上 Nacos 3.0 的标签,欢迎大家进行领取一起参与到 Nacos 3.0 的贡献。

 

 

Nacos的一致性算法

1. CAP原则

又称CAP定理,指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)。

CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。

2. Raft算法

Nacos 集群为了保证集群中数据的一致性,其采用了 Raft 算法,是通过对日志进行复制管理来达到一致性的算法。

Raft 算法是强一致性算法。

Nacos 同时支持 AP 与 CP,默认情况下,Nacos 集群是 AP 的。

Raft算法将Server划分为三种角色:

  • Leader:负责处理客户端读和写请求的节点,同时负责日志复制工作,一个集群中只有一个Leader。
  • Follower:可以处理客户端读请求,负责同步来自于 Leader 的日志,当接收到其它Cadidate 的投票请求后可以进行投票;当发现 Leader 挂了,其会转变为 Candidate 发起Leader 选举。
  • Candidate:一种临时的角色,只存在于leader的选举阶段(Leader 选举的候选人),某个节点想要变成leader,那么就发起投票请求,同时自己变成candidate。如果选举成功,则变为candidate,否则退回为follower

3.选举

Raft中使用心跳机制来出发leader选举。当服务器启动的时候,服务器成为follower。只要follower从leader或者candidate收到有效的RPCs就会保持follower状态。如果follower在一段时间内(该段时间被称为election timeout)没有收到消息,则它会假设当前没有可用的leader,然后开启选举新leader的流程。

Term(任期)

任期用连续的数字进行表示。每一个任期的开始都是一次选举(election),在某些情况下,有可能没有选出Leader,那么,将会开始另一个任期,并且立刻开始下一次选举。Raft 算法保证在一个任期内只有一个Leader.

过程

  1. follower增加当前的term;
  2. 转变为candidate;
  3. 向自己投票;
  4. 向其它节点发出投票请求。

投票

  1. 发来投票请求 candidate 的 term 和 log 编号不能小于当前 candidate 的 term 和 log 编号;
  2. 当前 term 内 candidate 的票还没投递给自己(一个 term 内每个节点都只有一票 );
  3. 接收到多个投票请求时,采取先到先得投递。

结果

当一个 Candidate 发出投票请求后会等待其它节点的响应结果。这个响应结果可能有三种情况:

  • 收到过半选票,成为新的 leader。然后会将消息广播给所有其它节点,产生新 Leader 了(其中包含其当前的 term);
  • 接收到别的 candidate 发来的新 leader 通知,比较新 leader 的 term 是否不比当前的 term小,则自己转变为 follower;
  • 没有收到过半选票,也没有收到新 leader 通知,则重新选举。
  • 票数相同时,采取随机选举超时处理:让这些 candidate 的选举在一个给定范围值内,各自随机的 timeout 之后开始,此时先到达 timeout 的 candidate 会先发出投票请求,并优先获取到投票。

4.数据同步/日志复制

主要作用是用于保证节点的一致性,这阶段所做的操作也是为了保证一致性与高可用性。

Raft 把每条日志都附加了 任期号和下标 来保证日志的唯一性.

当Leader选举出来后便开始负责客户端的请求,所有事务(更新操作)请求都必须先经过Leader处理。

  1. 在Raft中当接收到客户端的日志(事务请求)后先把该日志追加到本地的Log中;
  2. 然后通过 heartbeat 把该Entry同步给其他 Follower;
  3. Follower 接收到日志后记录日志然后向 Leader 发送ACK;
  4. 当 Leader 收到大多数(n/2+1)Follower的ACK信息后将该日志设置为已提交并追加到本地磁盘中;
  5. 通知客户端并在下个heartbeat中 Leader 将通知所有的Follower将该日志存储在自己的本地磁盘中。

5.脑裂

在一个高可用系统中,当联系着的节点因为网络连接断开联系时,本来为一个整体的系统,分裂成两个独立节点,两个节点开始争抢共享资源造成系统混乱、数据损坏的现象,成为“脑裂”。

列如:FollowerA由于网络问题感知不到Leader存在,FollowerA与FollowerB之间是相连的,此时FollowerA会发起选举,虽然 FollowerB能够感知到 Leader,但由于其接收到了更大 term 的投票请求,所以 FollowerB也就放弃了Leader,参与了新 Leader 的选举。新Leader的写请求并不会同步到原Leader节点上。而之前的Leader由于无法获取过半响应而无法处理写操作请求,不过并没有被Down,其仍为 Leader。所以之前Leader的数据是不会发生变更的。此时就形成了数据的不一致。

解决方案:通过时间续约和term比较最终旧leader被同步为follower。

posted @ 2023-01-09 09:30  jiuchengi  阅读(4204)  评论(0编辑  收藏  举报