SpringCloud Alibaba Nacos入门及原理解析

一、介绍    

    Nacos,英文全称Dynamic Naming and Configuration Service,Na为naming命名,co为configuration配置,s为服务,动态命名与配置服务。

    Nacos主旨是一个易于构建云原生应用的动态服务发现、配置管理和服务管理平台。它包含了注册中心、配置中心、健康检查、动态DNS、服务元数据和流量管理等功能。

直接看一张Nacos的架构图:

image

从图可以大概知道,

①服务提供者通过Nacos客户端向Nacos注册信息,消费者通过Nacos客户端从Nacos拉取信息

②Nacos客户端与Nacos服务通过OpenAPI交互,根据功能需要使用了http/dns/udp/tls协议

③包含配置服务和命名服务(指通过指定的名字来获取资源、服务的地址或提供者的信息)

④支持集群

⑤一致性协议包括priv-raft/sync renew/rdbms based

⑥提供管理控制台

 

二、同类产品

大概对比一下同类型的组件

 ZookeeperEurekaConsulNacos
一致性协议

CP模型,ZAB算法,

数据强一致性

AP模型,数据最终一致性

AP模型,Raft+Gossip算法,

数据最终一致性

AP + CP + 模型
健康检查Keep AliveClient BeatTCP/HTTP/gRPC/CmdTCP/HTTP/MYSQL/Client Beat
负载均衡策略不支持RibbonFabio权重/metadata/Selector
雪崩保护不支持支持不支持支持
自动注销实例支持支持不支持支持
访问协议TCPHTTPHTTP/DNSHTTP/DNS
分组不支持不支持不支持可根据环境和业务分组

 

三、Nacos安装使用:

1.前往https://github.com/alibaba/nacos/releases下载最新安装包nacos-server-1.1.4.zip

2.进入bin/目录执行startup.sh或者startup.cmd(Nacos有两种运行模式,单机或集群模式)

sh bin/startup.sh -m standalone
sh bin/startup.sh -m cluster

3.访问http://127.0.0.1:8848/nacos/即可进入控制台,默认账户密码为nacos

4.nacos内置了derby数据库,默认所有数据存储到该数据库上。可以通过修改conf/application.properties,添加

spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://192.168.2.183:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=iplastest
db.password=123456

这样的话就可以使用自己的mysql数据库了。

5.linux默认启动集群模式 + mysql,windows默认启动单机模式 + derby

 

四、代码调用

     Nacos分为服务端和客户端,服务端采用Java编写,为客户端提供注册中心和配置中心。nacos提供了openApi和多种语言的sdk(底层依然是调用openApi),有了基于http的openApi则可以兼容任何语言,从而使用nacos进行服务注册,配置存储。

1.使用Java sdk实现发布/获取/订阅配置:

特别说明:

①命名空间namespace 用于环境资源隔离,如区分生产和开发环境,需在控制台上新建命名空间,然后拿到对应的id

properties.setProperty("namespace", "a5d13b9e-58bc-4be6-ad0e-c85f1e63d552");

②data id 通常用于区分项目名或文件名,如order-service.properties、mysql.yml、redis.yml、es.properties

③group 通常用于区分业务配置,如Buy 或 Trade

④content为保存的配置内容

boolean publishConfig(String dataId, String group, String content) throws NacosException;

2.使用Java sdk实现服务注册/发现/订阅:

特别说明:

①获取健康实例接口使用到了随机策略 + 权重的负载均衡

②控制台允许设置服务流量权重,想增大流量则可以把实例的权重配置大一点,不接受流量把权重设置为0

③控制台可以对服务实例的元数据进行管理,格式为json,可以存储一些自定义的配置

④控制台可以实现服务优雅上线下线

3.使用spring注解的方式

依赖:

<dependency>
    <groupId>com.alibaba.nacos</groupId>
    <artifactId>nacos-spring-context</artifactId>
    <version>0.3.1</version>
</dependency>

代码:(虽然用了springboot项目,但是没有使用starter,用的还是spring注解方式)

@SpringBootApplication
@RestController
@NacosPropertySource(dataId = "nacos-test", autoRefreshed = true) // 加载配置源,dataId为读取的配置id
@EnableNacos(
        globalProperties =
        @NacosProperties(serverAddr = "${nacos.server-addr:localhost:8848}")
)
public class SingleNacosApplication {

    /**
     * 发布配置
     * */
    @NacosInjected
    private ConfigService configService;

    @GetMapping("/publishConfig")
    public String publishConfig(@RequestParam String content) throws NacosException {
        boolean result = configService.publishConfig("nacos-test", "DEFAULT_GROUP", content);
        if (result) {
            return "OK";
        }
        return "FAIL";
    }

    /**
     * 读取配置
     * */
    @GetMapping("/getConfig")
    public String getConfig() throws NacosException {
        return configService.getConfig("nacos-test", "DEFAULT_GROUP", 2000);
    }

    /**
     * 另外一种读取配置
     * */
    @NacosValue(value = "${test.properties.defaultName:无名氏}", autoRefreshed = true)
    private String defaultName;

    @GetMapping("/hi")
    public String hi() {
        return "hi " + defaultName;
    }

    @NacosInjected
    private NamingService namingService;

//    @PostConstruct
//    public void registerInstance() throws NacosException {
//        namingService.registerInstance("test-service", "192.168.0.101", 8888);
//    }

    /**
     * 服务注册
     * */
    @GetMapping("/setInstance")
    public String setInstance() throws NacosException {
        namingService.registerInstance("test-service", "192.168.0.101", 8888);
        namingService.registerInstance("test-service", "192.168.0.102", 8888);
        namingService.registerInstance("test-service", "192.168.0.103", 8888);
        namingService.registerInstance("test-service", "192.168.0.104", 8888);
        return "ok";
    }

    /**
     * 服务发现
     * */
    @GetMapping("/getInstance")
    public List<Instance> getInstance() throws NacosException {
        return namingService.getAllInstances("test-service");
    }

    /**
     * 获取一个健康实例
     * */
    @GetMapping("/getOneInstance")
    public Instance getOneInstance() throws NacosException {
        return namingService.selectOneHealthyInstance("test-service");
    }

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

}

4.还有springboot以及springcloud使用方式。

5.使用openApi实现服务注册/发现、发布/获取配置:

  • 服务注册
curl -X POST 'http://127.0.0.1:8848/nacos/v1/ns/instance?serviceName=order-services&ip=66.66.66.66&port=8080'
  • 服务发现
curl -X GET 'http://127.0.0.1:8848/nacos/v1/ns/instances?serviceName=order-services'
  • 发布配置
curl -X POST "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=test&group=test&content=REDIS_PORT=6379"
  • 获取配置
curl -X GET "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=test&group=test"

 五、原理实现

1.配置中心订阅

     Nacos 的配置信息保存到服务端的数据库中,客户端连接到服务端之后,根据 namespace (不填默认是public),dataID,group可以获取到具体的配置信息,当服务端的配置发生变更时,客户端订阅会收到通知。

     客户端是通过一个长连接来监听的配置项的数据,Nacos服务端则把订阅轮询存放在一个allSubs队列中,

当用户修改配置时,将配置信息入库并执行通知事件方法。

事件方法会从队列中取出相关长轮询订阅的客户端,然后通知客户端配置变更。

 

客户端收到服务端的配置变更消息,客户端将会获取到最新的数据,然后计算数据内容的MD5,跟cache中的MD5进行比较,如果不同则会重新保存配置信息到磁盘。

此时还会对绑定的 Listener 触发回调。

 

2.一致性算法

     一致性方案业界只有两种,一种是基于 Leader 的非对等部署的单点写一致性,一种是对等部署的多写一致性。

Nacos支持三种模式:AP、CP和 MIXED 。

这里的模式,指的是是CAP理论里的C、A和P概念。MIXED 代表AP + CP并存。

C:Consistency数据一致性,即所有分布式节点在同一时间看到的数据是一致的。

A:Availability服务可用性,即任何时间集群都能响应客户端的请求。

P:Partition tolerance分区容错性,任何分区发生故障时,仍然能够对外提供满足一致性和可用性的服务,除非整个网络环境都发生了故障。

CAP原则是三者只能选其二,在分布式系统中没有一种设计可以同时满足CAP三个特性。

 

    Nacos的一致性协议实现,一个是基于简化的 Raft 的 CP 一致性,一个是基于自研协议 Distro 的 AP 一致性。Raft 协议是基于 Leader 进行写入,其 CP 也并不是严格的,只是能保证一半所见一致,以及数据的丢失概率较小。Distro 协议则是参考开源 Eureka,各个节点都是平等的,在网络稳定时会自动同步到其他节点,弱一致性。

Nacos注册中心的设计原理详解

  • AP模式为了服务的可能性而减弱了一致性,因此AP模式下只支持注册临时实例。在AP模式下不能编辑服务的元数据等非实例级别的数据,但允许创建一个默认配置的服务。同时注册实例前不需要进行创建服务的操作,因为这种模式下,服务其实降级成一个简单的字符串标识。
  • CP模式下则支持注册持久化实例。网络正常情况下,允许编辑存储实例配置信息,在注册实例前必须要先注册服务。
  • MIXED 模式主要是为了能够同时支持临时实例和持久化实例的注册。这种模式下,注册实例之前必须创建服务。

     何时选择使用何种模式?一般来说,如果需要在服务级别编辑或者存储配置信息,那么 CP 是必须要使用的模式,如果不需要存储服务级别的信息,且服务实例是通过nacos-client注册,并能够保持心跳上报,那么就可以选择AP模式。

使用如下请求进行Server运行模式的设定:

curl -X PUT
'$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP'

 

3.服务实例健康检查

客户端调用naming.registerInstance进行服务注册时,会同时创建发送心跳信息的定时任务,不断请求服务端/instance/beat接口

最终服务端的接口/instance/beat里面会更新该实例的最后心跳时间

 

另外一边,服务端有个定时任务ClientBeatCheckTask每5秒会检查一次

检查最近心跳时间是否超过默认15秒超时时间,超时则把实例设置为不健康状态

如果最近心跳时间超过默认30秒超时时间,则会删除该实例

 

六、总结

(1)从功能上看,Nacos自带服务优雅上下线、负载均衡和流量管理(API+后台管理页面),具有分组隔离功能,一套Nacos集群可以支撑多项目、多环境。
(2)从部署来看,Nacos整合了注册中心、配置中心功能,把原来两套集群整合成一套,简化了部署维护。
(3)从伸缩性和扩展性来看,Nacos支持跨注册中心同步,而Eureka和Zookeeper都不支持,且在伸缩扩容方面,Nacos比Eureka、Zookeeper更优(nacos支持大数量级的集群)。
(5)从性能上看,配置中心读写性能方面,Nacos的tps比apollo更强一些。

 

     Nacos刚刚开源不久,由国产大佬牵头,目前在功能上看,算是一个集大成者。刚好遇上Eureka2.0闭源,社区逐渐火热,以后也会增加更多的新特性,成为主流指日可待。

 

 

 

参考:

Nacos仓库:https://github.com/nacos-group

主流微服务注册中心浅析和对比:https://www.jianshu.com/p/d1b5c8b76194

Nacos中文文档:https://nacos.io/zh-cn/docs/what-is-nacos.html

Nacos 1.0.0 功能预览:https://www.jianshu.com/p/7342f3a63094

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值