作者:廖春涛(春少)
https://www.yuque.com/docs/share/17664885-e0d8-40fd-a208-f1b58794d544
经过一年多发展,1.2.0版本已经从安全上解决上生产的最后疑虑,解决用户主要诉求。
经过社区讨论,从1.3.0版本开始修炼内功,聚焦“简单”、“性能”、“高可用”这核心的三个点进一步提升Nacos核心竞争力。今天很高兴能代表社区向大家介绍1.3.0的核心特性
- 内嵌关系型分布式数据库,简化集群部署模式
- 集群管理下沉统一,提供全新集群管理能力
- 一致性协议抽象升级,提供更高的性能
- 安全升级,解决Fastjson和越权风险
下面我们逐个介绍一下这些能力
轻量级的内嵌关系型分布式数据库
为什么只是用服务发现模块也要我部署MySQL?MySQL集群搭建的成本有多高?不能把集群部署简单一点,像Consul、Etcd那样子?
这不,为了解决这个问题,Nacos 1.3.0 借鉴了 Etcd 的通过Raft协议将单机KV存储转变为分布式的KV存储的设计思想,基于SOFA-JRaft以及Apache Derby构建了一个轻量级的分布式关系型数据库,同时保留了使用外置数据源的能力,用户可以根据自己的实际业务情况选择其中一种数据存储方案。
从Nacos 1.3.0版本开始集群部署可以不依赖MySQL的这个特性,不仅降低中小用户的集群运维部署成本,也简化了其集群部署的操作以及省去了部署一套数据库集群的操作。
新特性的开启命令为
代码语言:javascript复制./startup.sh -p embedded
然后查看启动日志是否有出现以下信息:Nacos started successfully in cluster mode. use embedded storage
同时,为了方便用户查询本机节点的数据同步情况,Nacos 1.3.0 配置模块开放了新的运维 Open-API,供其查询当前节点本地数据存储情况,并且该Open-API只能执行select语句,其他DML语句一概不支持,其使用方式如下
代码语言:javascript复制GET /nacos/v1/cs/ops/derby?sql=select * from config_info
使用该命令时,最好加上分页查询,避免一次查处大量的数据影响Nacos的正常对外业务工作,如果没有加上分页查询,则会自动添加分页查询语句,默认查询最开始的1k条数据。其分页查询的SQL的例子如下。
代码语言:javascript复制select * from config_info OFFSET 0 ROWS FETCH NEXT 1000 ROWS ONLY
其数据返回结果如下
代码语言:javascript复制{ "code":200, "message":null, "data":[ { "ID":242149783664332800, "DATA_ID":"application.properties", "GROUP_ID":"DEFAULT_GROUP", "TENANT_ID":"", "APP_NAME":"", "CONTENT":"this.is.test=liaochuntao", "MD5":"bedbfd7069e999edf2adf9d8a1af3083", "GMT_CREATE":"2020-06-03T05:30:47.345 0000", "GMT_MODIFIED":"2020-06-03T05:30:47.345 0000", "SRC_USER":null, "SRC_IP":"127.0.0.1", "C_DESC":null, "C_USE":null, "EFFECT":null, "TYPE":"properties", "C_SCHEMA":null } ]}
Nacos 1.3.0 构建的轻量级的分布式关系型存储,其已满足事务ACID性质。后面我们会在这基础之上进一步优化该存储的性能。
注意事项
分布式ID——Snowflake
Nacos 1.3.0的分布式存储,其数据的主键依赖雪花ID算法进行生成,雪花算法ID需要DataCenterId、WorkerId,默认情况下,_WorkerId不需要进行设置,会根据InetAddress.getLocalHost()进行计算生成。如果需要自己指定,则在application.properties进行如下配置设置
代码语言:javascript复制### set the dataCenterID manuallynacos.core.snowflake.data-center=Number### set the WorkerID manuallynacos.core.snowflake.worker-id=Number
数据迁移
由于Nacos 1.3.0新增的内嵌存储模式是全新的数据存储模式,因此在进行Nacos-Server升级时,如果是需要使用这种新能力,需要另外部署一个Nacos 1.3.0集群,然后进行数据迁移,由于Nacos 1.3.0 新增的内嵌存储模式,还无法自动的将原本MySQL的数据直接一键进行数据迁移,因此用户只能使用控制台的数据导出导入的方式进行(会丢失配置历史数据),更加完备的数据迁移功能会在后面的版本进行开放。
全新的集群管理
提供全新集群管理页面
Nacos 1.3.0版本开始,对集群节点管理进行了统一,将原有配置模块以及服务模块的集群节点管理统一下沉到内核模块,并且优化了集群节点信息展示,使得其更贴近Nacos集群节点的数据信息展示,其显示的内容包括如下几个方面
- 服务发现模块旧的Raft协议的元数据数据
- 配置管理模块使用新Raft协议的元数据
- Nacos节点自身的元数据信息
- 新Raft协议的RPC端口
- 节点的版本信息
- 节点的权重信息(该权重的功能暂未提供,以后服务端节点的负载均衡使用)
- 节点元数据信息上次刷新时间
新的集群寻址模式设置
Nacos 1.3.0版本开始,对集群节点的寻址模式做了统一,将原本分散的节点寻址模式整合并抽象,方便将来可以扩宽Nacos的集群发现机制,用户可以通过如下设置自己选择需要使用哪一种寻址模式作为集群节点的管理
文件寻址模式
代码语言:javascript复制nacos.core.member.lookup.type=file(默认值)
地址服务寻址模式
代码语言:javascript复制nacos.core.member.lookup.type=address-server
全新的一致性协议
Nacos 1.3.0版本开始,将对现有的一致性协议层进行统一抽象以及下沉。在Raft的选型上,使用了SOFA-JRaf作为CP协议的Backend,并且将其与配置管理模块进行了对接。用户可以通过调整下面的参数对Raft协议进行调整。
代码语言:javascript复制# Sets the Raft cluster election timeout, default value is 5 second# 设置Raft群集选举超时,默认值为5秒nacos.core.protocol.raft.data.election_timeout_ms=5000# Sets the amount of time the Raft snapshot will execute periodically, default is 30 minute# 设置Raft快照定期执行的时间,默认值为30分钟nacos.core.protocol.raft.data.snapshot_interval_secs=30# Raft internal worker threads# Raft 内部工作线程数量nacos.core.protocol.raft.data.core_thread_num=8# Number of threads required for raft business request processing# Raft 业务请求处理所需的线程数nacos.core.protocol.raft.data.cli_service_thread_num=4# raft 线性读取策略,默认为ReadOnlySafe,可以选择ReadOnlyLeaseBasednacos.core.protocol.raft.data.read_index_type=ReadOnlySafe### rpc请求超时,默认5秒nacos.core.protocol.raft.data.rpc_request_timeout_ms=5000
线性读参数解析
- ReadOnlySafe
- 该线性读模式,每次Follower进行读请求时,需要和Leader同步日志提交位点信息,而Leader,需要向过半的Follower发起证明自己是Leader的轻量的RPC请求,相当于一个Follower读,至少需要1 (n/2) 1 次的RPC请求。
- ReadOnlyLeaseBased
- 该线性读模式,每次Follower进行读请求时,Leader只需要判断自己的Leader租约是否过期了,如果没有过期,直接可以回复Follower自己是Leader,但是该机制对于机器时钟要求很严格,如果有做时钟同步的话,可以考虑使用该线性读模式。
如果说对于配置的发布、修改操作比较频繁,可以将Raft快照的时间适当的进行调整,避免新节点加入或者节点重启时,由于Raft日志回放操作数太多导致节点可开始对外服务的时间过长。
JRaft
同时,为了方便运维对新的Raft协议能够进行一些简单的运维操作,Nacos 1.3.0 内核模块开放了相关一致性协议运维的 Open-API,供其对Raft进行一些运维操作,其相关的运维操作如下
切换某一个Raft Group的Leader节点
代码语言:javascript复制POST /nacos/v1/core/ops/raft{ "groupId": "xxx", "command": "transferLeader" "value": "ip:{raft_port} or ip:{raft_port},ip:{raft_port},ip:{raft_port}"}
重置某一个Raft Group的集群成员
代码语言:javascript复制POST /nacos/v1/core/ops/raft{ "groupId": "xxx", "command": "resetRaftCluster", "value": "ip:{raft_port},ip:{raft_port},ip:{raft_port},ip:{raft_port}"}
注意,该操作是一个高危操作,仅仅当Raft集群的 n/2 1节点crash之后无法满足过半投票的要求才可以使用该运维命令,用于快速让当前剩余的节点重组Raft集群,对外提供服务,但是这个操作很大程度会造成数据的丢失
触发某一个Raft Group执行快照操作
代码语言:javascript复制POST /nacos/v1/core/ops/raft{ "groupId": "xxx", "command": "doSnapshot", "value": "ip:{raft_port}"}
移除某一个Raft Group中的某一成员
代码语言:javascript复制POST /nacos/v1/core/ops/raft{ "groupId": "xxx", "command": "removePeer", "value": "ip:{raft_port}"}
批量移除某一个Raft Group中的多个成员
代码语言:javascript复制POST /nacos/v1/core/ops/raft{ "groupId": "xxx", "command": "removePeers", "value": "ip:{raft_port},ip:{raft_port},ip:{raft_port},..."}
后续
目前一致性协议层只是将CP协议具体实现了,后面会再将AP协议——Distro下沉到一致性协议层中,并且调整Distro的实现,其协议内部的通信将使用gRPC,以配合Nacos对于整个通信通道的规划。同时真正实现对整个一致性协议使用方式的收拢。
安全升级
- 修复fastjson安全漏洞
- 修复tenant越权漏洞
贡献者
Nacos 1.3.0 版本的开发中,社区同学贡献了很大的力量,在此表示感谢,他们是(排序不分先后):@KomachiSion @zongtanghu @wangweizZZ @Maijh97 @jintonghuoya @jzdayz @yfh0918 @wolfgangzhu @ObserverYu @langghaha @jiangcaijun @wfnuser @TsingLiang @showkawa @yanlinly @chuntaojun