简介
r-nacos是一个用rust实现的nacos服务。
r-nacos是一个轻量、 快速、稳定、高性能的服务;包含注册中心、配置中心、web管理控制台功能,支持单机、集群部署。
r-nacos设计上完全兼容最新版本nacos面向client sdk 的协议(包含1.x的http OpenApi,和2.x的grpc协议), 支持使用nacos服务的应用平迁到 r-nacos。
r-nacos相较于java nacos来说,是一个提供相同功能,启动更快、占用系统资源更小、性能更高、运行更稳定的服务。
适用场景
- 开发测试环境使用nacos,nacos服务可以换成r-nacos。启动更快,秒启动。
- 个人资源云服务部署的 nacos,可以考虑换成r-nacos。资源占用率低: 包10M 出头,不依赖 JDK;运行时 cpu 小于0.5% ,小于5M(具体和实例有关)。
- 使用非订制nacos服务 ,希望能提升服务性能与稳定性,可以考虑迁移到 r-nacos。
功能说明
这里把 nacos 服务的功能分为三块 1、面向 SDK 的功能 2、面向控制台的功能 3、面向部署、集群的功能
每一块做一个对nacos服务的对比说明。
一、面向 SDK 的功能
访问认证:
- 有提供获取认证token的接口
- 实际请求暂不支持认证,都算认证通过。
配置中心:
- 支持配置中心的基础功能、支持维护配置历史记录
- 兼容配置中心的SDK协议
- 暂不支持灰度发布、暂不支持tag隔离
注册中心:
- 支持注册中心的基础功能
- 兼容配置中心的SDK协议
- 暂不支持1.x的 udp 实例变更实时通知,只支持 2.x 版本grpc实例变更实时通知 。最开始的版本也有支持过udp实例变更 通知,后面因支持 grpc 的两者不统一,就暂时去掉,后继可以考虑加回去。
二、面向控制台的功能
访问认证: 暂时不开启认证
命名空间:
- 支持管理命名空间列表
- 支持切换命名空间查询配置、服务数据。
配置中心:
- 支持配置中心信息管理
- 支持配置导入、导出,其文件格式与nacos兼容
- 支持配置历史记录查看与恢复
- 暂不支持tag的高级查询
- 暂不支持查询配置监听记录
服务中心:
- 支持注册中心的服务、服务实例管理
- 暂不支持查询监听记录
三、面向部署、集群的功能
- 支持单机部署
- 支持集群部署。集群部署配置中心数据使用raft+节点本地存储组成的分布式存储,不需要依赖mysql。具体参考 集群部署说明
快速开始
一、 安装运行 r-nacos
【单机部署】
方式1:从 github release 下载对应系统的应用包,解压后即可运行。
linux 或 mac
# 解压
tar -xvf rnacos-x86_64-apple-darwin.tar.gz
# 运行
./rnacos
windows 解压后直接运行 rnacos.exe 即可。
方式2: 通过docker 运行
#stable是最新正式版本号,也可以指定镜像版本号,如: qingpan/rnacos:v0.4.0
docker pull qingpan/rnacos:stable
docker run --name mynacos -p 8848:8848 -p 9848:9848 -p 10848:10848 -d qingpan/rnacos:stable
docker 的容器运行目录是 /io,会从这个目录读写配置文件
docker 版本说明
应用每次打包都会同时打对应版本的docker包 ,qingpan/rnacos:$tag 。
每个版本会打两类docker包
docker包类型 | tag 格式 | 示例 | 说明 |
---|---|---|---|
gnu debian包 | $version | qingpan/rnacos:v0.4.0 | docker包基于debian-slim,体积比较大(压缩包36M,解压后102M),运行性能相对较高; |
musl alpine包 | $version-alpine | qingpan/rnacos:v0.4.0-alpine | docker包基于alpine,体积比较小(压缩包11M,解压后34M),运行性能相对较低; |
如果不观注版本,可以使用最新正式版本tag:
- 最新的gnu正式版本:
qingpan/rnacos:stable
- 最新的alpine正式版本:
qingpan/rnacos:stable-alpine
方式3:通过 cargo 编译安装
# 安装
cargo install rnacos
# 运行
rnacos
方式4: 下载源码编译运行
git clone https://github.com/heqingpan/rnacos.git
cd rnacos
cargo build --release
cargo run --release
方式5: MacOS支持通过brew安装
# 把r-nacos加入taps
brew tap r-nacos/r-nacos
# brew 安装 r-nacos
brew install r-nacos
# 运行
rnacos
# 后续可以直接通过以下命令更新到最新版本
# brew upgrade r-nacos
测试、试用推荐使用第1、第2种方式,直接下载就可以使用。
在linux下第1、第2种方式默认是musl版本(性能比gnu版本差一些),在生产服务对性能有要求的可以考虑使用第3、第4种在对应环境编译gnu版本部署。
启动配置可以参考: 运行参数说明
二、运行nacos 应用
服务启动后,即可运行原有的 nacos 应用。
配置中心http api例子
# 设置配置
curl -X POST 'http://127.0.0.1:8848/nacos/v1/cs/configs' -d 'dataId=t001&group=foo&content=contentTest'
# 查询
curl 'http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=t001&group=foo'
注册中心http api例子
# 注册服务实例
curl -X POST 'http://127.0.0.1:8848/nacos/v1/ns/instance' -d 'port=8000&healthy=true&ip=192.168.1.11&weight=1.0&serviceName=nacos.test.001&groupName=foo&metadata={"app":"foo","id":"001"}'
curl -X POST 'http://127.0.0.1:8848/nacos/v1/ns/instance' -d 'port=8000&healthy=true&ip=192.168.1.12&weight=1.0&serviceName=nacos.test.001&groupName=foo&metadata={"app":"foo","id":"002"}'
curl -X POST 'http://127.0.0.1:8848/nacos/v1/ns/instance' -d 'port=8000&healthy=true&ip=192.168.1.13&weight=1.0&serviceName=nacos.test.001&groupName=foo&metadata={"app":"foo","id":"003"}'
# 查询服务实例
curl "http://127.0.0.1:8848/nacos/v1/ns/instance/list?&namespaceId=public&serviceName=foo%40%40nacos.test.001&groupName=foo&clusters=&healthyOnly=true"
具体的用法参考 nacos.io 的用户指南。
三、使用r-nacos控制台
从0.4.0版本开始,支持独立端口号的新控制台。新控制台有完备的用户管理、登陆校验、权限控制,支持对外网暴露。
启动服务后可以在浏览器通过 http://127.0.0.1:10848/rnacos/
访问r-nacos新控制台。
老控制台http://127.0.0.1:8848/rnacos/
标记废弃,默认不开启,可通过配置开启。老控制台不需要登陆鉴权、不支持用户管理。
主要包含用户管理、命名空间管理、配置管理、服务管理、服务实例管理。
1、用户登陆
在新控制台打开一个地址,如果检测到没有登陆,会自动跳转到登陆页面。 一个用户连续登陆失败5次,会被锁定1个小时。这个次数可以通过启动参数配置。
2、用户管理
系统会默认创建一个名为admin
的用户,密码为admin
(也可以通过环境变量 RNACOS_INIT_ADMIN_USERNAME 和 RNACOS_INIT_ADMIN_PASSWORD 修改默认账号的账户名和密码)。
进去控制台后可按需管理用户。
用户角色权限说明:
- 管理员: 所有控制台权限
- 开发者:除了用户管理的所有控制台权限
- 访客:只能查询配置中心与注册中心的数据,没有编辑权限。
注意: 对外暴露的nacos控制台端口前,建议增加一个自定义管理员,把admin用户删除或禁用。
3、配置管理
配置列表管理
新建、编辑配置
4、服务列表管理
5、服务实例管理
6、命名空间管理
集群部署
r-nacos 在v0.3.0版本后支持集群部署。
集群功能机制简介
集群部署的目标是通过多实例部署的方式,支持服务的水平扩容,支持部分节点异常后继续提供服务,提升稳定性。
配置中心
配置中心使用raft集群协议+本地存储,持久化数据,不需要再依赖 mysql 存储配置。其持久化机制类似etcd
。
请求方式 | 说明 | 性能 |
---|---|---|
写入 | 只有主节点能写入,其它节点收到写入请求后转发到主节点写入 | 集群2千tps左右,有优化空间 |
读取 | 每个节点都能读取全量数据 | 单节点8万qps左右,集群总容量为n*8万 |
注册中心
注册中心使用类distor协议,同步集群间的数据。
注册中心复用配置中心节点列表信息,两者协议是分别单独实现的。
请求方式 | 说明 | 性能 |
---|---|---|
写入 | 注册中心每个节点平等,按hash划分每个节点负责的内容;节点对负责的服务可写,否则转发到对应负责的节点处理。 | 集群1万tps左右 |
读取 | 每个节点都能读取全量数据 | 单节点3万qps左右,集群总容量为n*3万 |
集群部署
集群部署和单机部署步骤一致,只是对应的运行参数不同,增加了集群节点的配置。
一、取得r-nacos安装包
安装包的获取方式与 快速开始一致
二、配置集群规则
集群部署相关的配置参数有四个:RNACOS_RAFT_NODE_ID,RNACOS_RAFT_NODE_ADDR,RNACOS_RAFT_AUTO_INIT,RNACOS_RAFT_JOIN_ADDR。
具体参数说明参考 运行参数说明
集群配置规则:
- 所有的集群节点都需要设置RNACOS_RAFT_NODE_ID,RNACOS_RAFT_NODE_ADDR ,其中不同节点的node_id和 node_addr不能相同;node_id为一个正整数,node_addr为
ip:grpc_port
- 集群主节点: 初始设置RNACOS_RAFT_AUTO_INIT为true (如果节点为1,默认是 true,不用额外设置)。
- 集群从节点: 初始设置RNACOS_RAFT_AUTO_INIT为false (节点非1,默认就是false,不用额外设置);另外需要设置RNACOS_RAFT_JOIN_ADDR为当前主节点的地址,以方便启动时自动加入集群中。
- 第2、3点只是为了初始化组建集群。集群运行起来之后,后继启动配置从raft db中加载。
- 集群节点数量不要求,可以是1、2、3、4、... ; 不过raft协议只支持小于集群半数节点异常后继续提供写入服务(查询不影响)。例如:3个节点集群支持1个节点异常后提供写入服务,2个节点集群可以正常运行,不支持节点异常后提供服务。
- 从节点可以在使用过程中按需加入。比如原来3个节点,可能在使用一段时间后增加2个节点扩容。
实例:规划集群节点信息并编写对应的配置文件
按上面的配置规则,下面我们配置一个3节点集群例子。
初始化节信息
- 主节点id为1,地址为127.0.0.1:9848
- 第一个从节点id为2,地址为127.0.0.1:9849
- 第二个从节点id为3,地址为127.0.0.1:9849
正式集群部署的log等级建议设置为warn
,不打正常的请求日志,只打报警或异常日志,减少日志量。
配置信息如下
env01
#file:env01 , Initialize with the leader node role
RUST_LOG=warn
#RNACOS_INIT_ADMIN_USERNAME=admin
#RNACOS_INIT_ADMIN_PASSWORD=admin
RNACOS_HTTP_PORT=8848
RNACOS_RAFT_NODE_ADDR=127.0.0.1:9848
RNACOS_CONFIG_DB_DIR=db01
RNACOS_RAFT_NODE_ID=1
RNACOS_RAFT_AUTO_INIT=true
env02:
#file:env02 , Initialize with the follower node role
RUST_LOG=warn
#RNACOS_INIT_ADMIN_USERNAME=admin
#RNACOS_INIT_ADMIN_PASSWORD=admin
RNACOS_HTTP_PORT=8849
RNACOS_RAFT_NODE_ADDR=127.0.0.1:9849
RNACOS_CONFIG_DB_DIR=db02
RNACOS_RAFT_NODE_ID=2
RNACOS_RAFT_JOIN_ADDR=127.0.0.1:9848
env03:
#file:env03 , Initialize with the follower node role
RUST_LOG=warn
#RNACOS_INIT_ADMIN_USERNAME=admin
#RNACOS_INIT_ADMIN_PASSWORD=admin
RNACOS_HTTP_PORT=8850
RNACOS_RAFT_NODE_ADDR=127.0.0.1:9850
RNACOS_CONFIG_DB_DIR=db03
RNACOS_RAFT_NODE_ID=3
RNACOS_RAFT_JOIN_ADDR=127.0.0.1:9848
注: 上面的地址是本机运行多实例的地址,实际使用时换成具体的服务ip和port即可。
三、启动集群
第一次启动
分别运行三个节点,需要先运行主节点成功后再运行
先运行主节点
nohup ./rnacos -e env01 > n01.log &
主节点功能启动后,再运行从节点
nohup ./rnacos -e env02 > n02.log &
nohup ./rnacos -e env03 > n03.log &
实例过程中不同的节点需要在不同的服务器运行服务。
集群重启
节点重启和第一次启动的配置和启动方式不变。
集群启动后,集群的节点信息已久化节点本地数据库中。 在节点重启时后直接从本地数据库加载集群节点的信息。这时就不需要读取需要加入的集群地址,RNACOS_RAFT_JOIN_ADDR不会再被使用(留在配置中也不影响)。
部分节点重启,在重启一个心跳时间(0.5秒)就会被重新加入集群。
全部节点重启, raft需要启动静默5秒+选举超时3秒后才重新选举主节点;10秒左右集群才提供配置写入服务。 期间配置查询,和注册中心的读写可以正常使用。
四、运行应用使用集群
集群服务启动后,即可运行原有的 nacos 应用。
配置中心http api例子
echo "\npublish config t001:contentTest to node 1"
curl -X POST 'http://127.0.0.1:8848/nacos/v1/cs/configs' -d 'dataId=t001&group=foo&content=contentTest'
sleep 1
echo "\nget config info t001 from node 1, value:"
curl 'http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=t001&group=foo'
echo "\nget config info t001 from node 2, value:"
curl 'http://127.0.0.1:8849/nacos/v1/cs/configs?dataId=t001&group=foo'
echo "\nget config info t001 from node 3, value:"
curl 'http://127.0.0.1:8850/nacos/v1/cs/configs?dataId=t001&group=foo'
sleep 1
echo "\npublish config t002:contentTest02 to node 2"
curl -X POST 'http://127.0.0.1:8849/nacos/v1/cs/configs' -d 'dataId=t002&group=foo&content=contentTest02'
sleep 1
echo "\nget config info t002 from node 1, value:"
curl 'http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=t002&group=foo'
echo "\nget config info t002 from node 2, value:"
curl 'http://127.0.0.1:8849/nacos/v1/cs/configs?dataId=t002&group=foo'
echo "\nget config info t002 from node 3, value:"
curl 'http://127.0.0.1:8850/nacos/v1/cs/configs?dataId=t002&group=foo'
注册中心http api例子
echo "\nregister instance nacos.test.001 to node 1"
curl -X POST 'http://127.0.0.1:8848/nacos/v1/ns/instance' -d 'port=8000&healthy=true&ip=192.168.1.11&weight=1.0&serviceName=nacos.test.001&groupName=foo&metadata={"app":"foo","id":"001"}'
echo "\nregister instance nacos.test.001 to node 2"
curl -X POST 'http://127.0.0.1:8849/nacos/v1/ns/instance' -d 'port=8000&healthy=true&ip=192.168.1.12&weight=1.0&serviceName=nacos.test.001&groupName=foo&metadata={"app":"foo","id":"002"}'
echo "\nregister instance nacos.test.001 to node 3"
curl -X POST 'http://127.0.0.1:8850/nacos/v1/ns/instance' -d 'port=8000&healthy=true&ip=192.168.1.13&weight=1.0&serviceName=nacos.test.001&groupName=foo&metadata={"app":"foo","id":"003"}'
sleep 1
echo "\n\nquery service instance nacos.test.001 from node 1, value:"
curl "http://127.0.0.1:8848/nacos/v1/ns/instance/list?&namespaceId=public&serviceName=foo%40%40nacos.test.001&groupName=foo&clusters=&healthyOnly=true"
echo "\n\nquery service instance nacos.test.001 from node 2, value:"
curl "http://127.0.0.1:8849/nacos/v1/ns/instance/list?&namespaceId=public&serviceName=foo%40%40nacos.test.001&groupName=foo&clusters=&healthyOnly=true"
echo "\n\nquery service instance nacos.test.001 from node 3, value:"
curl "http://127.0.0.1:8850/nacos/v1/ns/instance/list?&namespaceId=public&serviceName=foo%40%40nacos.test.001&groupName=foo&clusters=&healthyOnly=true"
echo "\n"
如果在本地源码编译,可使用或参考test_cluster.sh 创建、测试集群。
具体的用法参考 nacos.io 的用户指南。
集群管理工具
通过控制台查看集群状态
在控制台页面主要观注集群节点列表状态与raft主角点是否正常
通过接口查看集群状态
- 查询指定节点的raft 集群状态
curl "http://127.0.0.1:8848/nacos/v1/raft/metrics"
# {"id":1,"state":"Leader","current_term":1,"last_log_index":10,"last_applied":10,"current_leader":1,"membership_config":{"members":[1,2,3],"members_after_consensus":null}}
# 主要关注 current_leader和members
- 增加节点
curl -X POST "http://127.0.0.1:8848/nacos/v1/raft/add-learner" -H "Content-Type: application/json" -d '[2, "127.0.0.1:9849"]'
推荐通过启动新节点时设置RNACOS_RAFT_JOIN_ADDR
加入集群。
如果配置时主节点不确定,可以启动后再调用主节点接口把新节点加入集群。
此接口也可以用于在集群运行期更新集群节点地址。
- 更新集群节点列表
curl -X POST "http://127.0.0.1:8848/nacos/v1/raft/change-membership" -H "Content-Type: application/json" -d '[1, 2, 3]'
如果通过手动方式增加节点,需要调用本接口更新集群节点列表。
此接口可以用于对集群缩容,下线指定节点。
附录介绍
部署参数说明
同一个应用包需要支持不同场景,就需要支持设置自定义参数。
r-nacos 运行参数支持通过环境变量,或指定配置文件方式设置。 如果不设置则按默认参数运行。
设置运行参数的方式
通过环境变更设置参数
例子:
RNACOS_HTTP_PORT=8848 ./rnacos
这种方式在自定义少量参数时比较方便
通过指定配置文件方式设置参数
例子
# 从0.3.0版本开始支持 -e env_file 运行参数
./rnacos -e env_file
如果不指定文件时也会尝试从当前目录下.env文件加载配置参数
env_file内容的格式是
KEY1=VALUE1
KEY2=VALUE2
KEY3=VALUE3
rnacos 运行时支持的环境变量,如果不设置则按默认配置运行。
运行参数说明
参数KEY | 内容描述 | 默认值 | 示例 | 开始支持的版本 |
---|---|---|---|---|
RNACOS_HTTP_PORT | rnacos监听http端口 | 8848 | 8848 | 0.1.x |
RNACOS_GRPC_PORT | rnacos监听grpc端口 | 默认是 HTTP端口+1000 | 9848 | 0.1.x |
RNACOS_HTTP_CONSOLE_PORT | r-nacos独立控制台端口 | 默认是 HTTP端口+2000;设置为0可不开启独立控制台 | 10848 | 0.4.x |
RNACOS_CONSOLE_LOGIN_ONE_HOUR_LIMIT | r-nacos控制台登录1小时失败次数限制 | 默认是5,一个用户连续登陆失败5次,会被锁定1个小时 | 5 | 0.4.x |
RNACOS_HTTP_WORKERS | http工作线程数 | cpu核数 | 8 | 0.1.x |
RNACOS_CONFIG_DB_FILE | 配置中心的本地数据库文件地址【0.2.x后不在使用】 | config.db | config.db | 0.1.x |
RNACOS_CONFIG_DB_DIR | 配置中心的本地数据库文件夹, 会在系统运行时自动创建【因语义原因,v0.6.x后推荐使用RNACOS_DATA_DIR】 | nacos_db | nacos_db | 0.2.x |
RNACOS_DATA_DIR | 本地数据库文件夹, 会在系统运行时自动创建【与RNACOS_CONFIG_DB_DIR等价,用于替代RNACOS_CONFIG_DB_DIR】 | linux,MacOS默认为~/.local/share/r-nacos/nacos_db;windows,docker默认为nacos_db | nacos_db | 0.6.x |
RNACOS_RAFT_NODE_ID | 节点id | 1 | 1 | 0.3.0 |
RNACOS_RAFT_NODE_ADDR | 节点地址Ip:GrpcPort,单节点运行时每次启动都会生效;多节点集群部署时,只取加入集群时配置的值 | 127.0.0.1:GrpcPort | 127.0.0.1:9848 | 0.3.0 |
RNACOS_RAFT_AUTO_INIT | 是否当做主节点初始化,(只在每一次启动时生效) | 节点1时默认为true,节点非1时为false | true | 0.3.0 |
RNACOS_RAFT_JOIN_ADDR | 是否当做节点加入对应的主节点,LeaderIp:GrpcPort;只在第一次启动时生效 | 空 | 127.0.0.1:9848 | 0.3.0 |
RNACOS_RAFT_SNAPSHOT_LOG_SIZE | raft打包snapshot镜像的日志数量;即变更日志超过这个值则会触发一次打包镜像 | 默认值10000 | 10000 | 0.5.0 |
RUST_LOG | 日志等级:debug,info,warn,error;所有http,grpc请求都会打info日志,如果不观注可以设置为error减少日志量 | info | error | 0.3.0 |
RNACOS_ENABLE_NO_AUTH_CONSOLE | 是否开启无鉴权控制台 | false | false | 0.5.2 |
RNACOS_CONSOLE_LOGIN_TIMEOUT | 控制台登陆有效时长(单位为秒) | 一天,86400秒 | 86400 | 0.5.0 |
RNACOS_GMT_OFFSET_HOURS | 日志时间的时区,单位小时;默认为本机时区,运行在docker时需要指定 | local | 8(东8区),-5(西5区) | 0.5.7 |
RNACOS_ENABLE_OPEN_API_AUTH | 是否对openapi开启鉴权;(注:nacos切换到r-nacos过程中不要开启鉴权) | false | true | 0.5.8 |
RNACOS_API_LOGIN_TIMEOUT | open api鉴权有效时长,单位为秒;(注:从不鉴权到开启鉴权,需要间隔对应时长以保证客户端token能更新生效) | 一小时,3600秒 | 3600 | 0.5.8 |
RNACOS_CLUSTER_TOKEN | 集群间的通信请求校验token,空表示不开启校验,设置后只有相同token的节点间才可通讯 | 空字符串 | 1234567890abcdefg | 0.5.8 |
RNACOS_INIT_ADMIN_USERNAME | 初始化管理员用户名,只在主节点第一次启动时生效 | admin | rnacos | 0.5.11 |
RNACOS_INIT_ADMIN_PASSWORD | 初始化管理员密码,只在主节点第一次启动时生效 | admin | rnacos123456 | 0.5.11 |
RNACOS_ENABLE_METRICS | 是否开启监控指标功能 | true | true | 0.5.13 |
RNACOS_METRICS_LOG_INTERVAL_SECOND | 监控指标采集打印到日志的间隔,单位秒,最小间隔为5秒 | 30 | 10 | 0.5.13 |
RNACOS_CONSOLE_ENABLE_CAPTCHA | 验证码的开关 | true | true | 0.5.14 |
注:从v0.3.0开始,默认参数启动的节点会被当做只有一个节点,当前节点是主节点的集群部署。支持其它新增的从节点加入。
性能与容量说明
压测工具
主要使用goose压测。
参考项目中的子工程 loadtest
性能压测结果
模块 | 场景 | 单节点qps/tps | 集群qps/tps | 总结/备注 |
---|---|---|---|---|
配置中心 | 配置写入,http协议 | 1.76万 | 7.6千 | 集群写入压测是在同一台电脑运行3个节点,如果换成多个机器部署,tps应该还能有所提升。 |
配置中心 | 配置查询,http协议 | 8万 | n*8万 | 集群的查询总qps是节点的倍数 |
注册中心 | 服务实例注册,http协议 | 4.8万 | 2.4万 | 集群写入压测是在同一台电脑运行3个节点,如果换成多个机器部署,tps应该还能有所提升。 |
注册中心 | 服务实例注册,grpc协议 | 4.8万 | 2.4万 | grpc协议压测工具没有支持,目前没有实际压测,理论不会比http协议低 |
注册中心 | 服务实例心跳,http协议 | 4.8万 | 2.4万 | 心跳是按实例计算和服务实例注册一致共享qps |
注册中心 | 服务实例心跳,grpc协议 | 8万以上 | n*8万 | 心跳是按请求链接计算,且不过注册中心处理线程,每个节点只需管理当前节点的心跳,集群总心跳qps是节点的倍数 |
注册中心 | 查询服务实例 | 3万 | n*3万 | 集群的查询总qps是节点的倍数 |
注: 具体结果和压测环境有关
压测记录
注册中心查询:
配置中心查询,两个进程分别限流4万qps同时压测(共8万qps),其中一个的压测记录:
容量分析
配置中心
- 配置中心的单机查询8万qps,很高,又支持水平扩容;集群基本没有查询瓶颈。
- 配置中心所占用的内存和配置内存有关,在内存没有满前,基本没有瓶颈。
- 配置中心集群写入时统一在主节点写入,写入可能有瓶颈;目前1.5千tps,后面优化后应该能到1万 tps以上。
注册中心
- 注册中心的单机查询3万qps,比较高,又支持水平扩容;集群基本没有查询瓶颈。
- 注册中心所占用的内存和配置内存有关,在内存没有满前,基本没有瓶颈。
- 注册中心集群写入时每个节点都要写一遍,整体集群的写入性能tps和单机理论上相当。
- http协议(v1.x版本)和grpc协议(v2.x)的心跳维护机制不同;http心跳是按实例计算和服务实例注册一致共享qps, grpc的心跳是按请求链接计算且不过注册中心处理线程。所有这类协议理论支持的容量差别很大。
注册中心集群注册容量推理
- http协议注册+心跳qps是1万,每个实例5秒钟一次心跳;理论上只能支持5万服务实例左右。
- grpc协议,注册qps假设也是1万,心跳qps单实例8万,3节点集群总心跳24万;如果平均一个应用实例1小时重连一次;支持注册的服务实例总数为:606010000 = 3600万,心跳支持的链接实例总数为:5*24万=120万个链接实例(和集群节点有关)。
结论: 如果使用v1.0x http协议,支持的实例在5万个左右。 如果使用v2.0x grpc协议,理论上基本没有瓶颈。
r-nacos与java nacos性能压测对比 (单机模式)
旧版本的单机压测记录,有和java 版本nacos的比较.
压测环境与工具
压测环境:macos i7四核 /16G , 施压、受压机器是同一台机器(会拉低压测结果)。 压测工具: * wrk ,qps: 24450左右 * goose, qps 17000左右 (单进程加限流施压比 wrk低) * 单进程施压请求wrk比goose 输出高
r-nacos server版本:v0.1.1 java nacos server版本: 2.1.0
因wrk,goose暂时不支持grpc协议,暂时只压测http协议接口
配置中心
配置中心,不会频繁更新,写入不做压测。
rust r-nacos server:
- 配置中心单机查询 wrk 压测 qps 在2.4万左右.
java nacos server:
- 配置中心单机查询 wrk 压测, qps 在7700左右
注册中心
rust r-nacos server:
- naming 注册1000 x 1个实例,每秒200qps,单核cpu: 4.5% 左右
- naming 单查询1.5万 QPS 左右
- wrk 查询单个服务 ,1.65万 qps
- goose 查询1000个服务 ,1.5万 qps
- naming 单注册服务
- goose,5万到7万实例数 0.7万 qps左右。
- 查询与注册混合
- wrk 查询单个服务(1.5万 qps) + goose 注册(0.075 万qps) 【5千实例】
- goose 查询1000个服务(1.3万 qps) + goose 注册(0.07万 qps) 【5千实例】
- wrk 查询单个服务(1.5万 qps) + goose 注册(0.15万qps) 【1万实例】
- goose 查询1000个服务(1.3万 qps) + goose 注册(0.13万 qps) 【1万实例】
java nacos server:
- 配置中心查询 wrk 压测, 7700 qps 左右
- naming 注册1000 x 1个实例,每秒200qps,单核cpu: 17% 左右
- naming 单查询
- wrk 查询单个服务 ,1.35万 qps 。
- goose 查询1000个服务,1万 qps(前期应该还能上去一些)。前30秒能稳定在1万左右,30秒后,跌到200左右之后再上下浮动,可能受 GC 影响。
- naming 单注册
- goose,5万到7万实例数 0.45万 qps左右。
- 查询与注册混合
- wrk 查询单个服务(1.3万 qps) + goose 注册(0.07 万qps) 【5千实例】
- goose 查询1000个服务(1万 qps) + goose 注册(0.07万 qps) 【5千实例】; 前期能保持,后期 qps 上下浮动比较大,最低小于50。
- wrk 查询单个服务(0.9万 qps) + goose 注册(0.12万qps) 【1万实例】
- goose 查询1000个服务(0.6万 qps) + goose 注册(0.08万 qps) 【1万实例】
性能压测总结
-
r-nacos,除了服务服务注册不能稳定在1万以上,其它的接口qps都能稳定在1万以上。
-
java 的查询接口基本能压到1万以上,但不平稳,后继浮动比较大。如果降低压测流程,qps 可以相对平稳。
-
在多服务查询叠加上多服务注册场景,r-nacos qps能稳定在1.3万左右, java nacos qps 下降明显在0.6万左右。
-
r-nacos 综合 qps是 java版的2倍以上,因 java 有 GC,qps水位稳定性上 java较差(相同施压流量,qps 能从峰值1万能降到1百以下)。
-
r-nacos 服务,线程数稳定在7,cpu 用例率最大200%左右(相当用个2核),内存在50M 以下
-
java nacos 服务,线程数最大300左右, cpu 用例率最大500%左右,内存600M到900M。
版本说明
R-NACOS版本说明
版本 | 对nacos兼容说明 | 版本特点说明 | 适用场景 |
---|---|---|---|
v0.3.3以上 | 支持2.x新最版nacos面向sdk的协议 | 支持集群部署版本,使用1个节点的集群方式当做单机模式,配置中心raft 协议没有充分优化,配置中心集群写入tps在1.5千左右 | 对配置中心没有太高频写入需求的应用都推荐使用这个版本 (后面会优化配置写入性能) |
v0.2.3 (不再推荐,新版bugfix暂定不再同步) | 支持2.x新最版nacos面向sdk的协议 | 单机部署版本,配置中心数据库使用sled, 初始内存多占用25M左右,配置中心单机写入tps在1.5万以上 | 对配置中心有高频写入需求的应用可以考虑使用 |
v0.1.10 (不再推荐,新版bugfix暂定不再同步) | 支持1.x服务接口;除了查询服务中心服务列表外,支持2.x大部分接口 | 单机部署版本,配置中心数据库使用sqlite,内存占用比较低,但配置写入tps不高,7百左右 | 不使用2.x的注册中心服务,对内存占用敏感的小应用可以考虑使用 |
docker 版本说明
应用每次打包都会同时打对应版本的docker包 ,qingpan/rnacos:$tag 。
每个版本会打两类docker包
docker包类型 | tag 格式 | 示例 | 说明 |
---|---|---|---|
gnu debian包 | $version | qingpan/rnacos:v0.4.2 | docker包基于debian-slim,体积比较大(压缩包36M,解压后102M),运行性能相对较高 |
musl alpine包 | $version-alpine | qingpan/rnacos:v0.4.2-alpine | docker包基于alpine,体积比较小(压缩包11M,解压后34M),运行性能相对较低 |
如果不关注版本,可以使用最新正式版本tag。
- 最新的gnu正式版本:
qingpan/rnacos:stable
- 最新的alpine正式版本:
qingpan/rnacos:stable-alpine
MacOS arm系统补充说明 :目前MacOS arm系统运行stable
镜像失败,可以先换成stable-alpine
镜像。等后面解决arm stable
镜像问题后再把这个注意事项去掉。
nacos client sdk
java nacos sdk
nacos-client
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>${nacos.version}</version>
</dependency>
协议 | 验证过版本 | 推荐版本 |
---|---|---|
grpc协议(2.x) | 2.1.0 | >2.1.x |
http协议(1.x) | 1.4.1 | >1.4.x |
go nacos sdk
nacos-sdk-go
nacos-sdk-go/v2 v2.2.5
协议 | 验证过版本 | 推荐版本 |
---|---|---|
grpc协议(2.x) | 2.2.5 | >=2.2.5 |
rust nacos sdk
nacos-sdk-rust
nacos-sdk = "0.3.3"
协议 | 验证过版本 | 推荐版本 |
---|---|---|
grpc协议 | 0.3.3 | >=0.3.3 |
nacos_rust_client
nacos_rust_client = "0.3.0"
协议 | 验证过版本 | 推荐版本 |
---|---|---|
同时支持http协议与grpc协议 | 0.3.0 | >=0.3.0 |
http协议 | 0.2.2 | >=0.2.2 |
常见问题
控制台查询不到信息
控制台查询配置信息,是按命名空间作隔离的。
要先确认创建的命名空间与控制台查询的命名空间是否一致。
如果不一致,先在命令空间
管理页面维护对应的命名空间,再到配置列表或服务列表切换到对应名命空间查询。
架构
r-nacos架构图
说明:
- r-nacos默认支持集群部署,单机就相当于一个节点的集群,后续有需要可以按需加入新的节点;
- 数据持久化使用raft协议分布式数据库(raft协议+节点文件存储),类似etcd;
- 只需对
RNACOS_CONFIG_DB_DIR:nacos_db
目录下的文件备份与恢复,即可实现数据的备份与恢复; - r-nacos控制台使用前后端分离架构;前端应用因依赖nodejs,所以单独放到另一个项目 r-nacos-console-web ,再通过cargo 把打包好的前端资源引入到本项目,避免开发rust时还要依赖nodejs。
多实例的raft和distro分布式协议说明待补充
配置中心
配置模型图
配置中心raft协议
raft协议的主要逻辑:
- 节点区分角色:leader(主节点),follower(从节点),candidate(选举节点);
- 稳定状态是一个主节点,多个从节点;
- 主节点负责写入,写入时需要先把写入日志同步到其它节点,超过半数节点写入日志成功后才能提交日志到状态机。
- 主节点需要定时发心跳到从节点,从节点如果超时未收到心跳,则会发起选举。选举时收到超过半数节点的同意,就可以切换成主节点。
具体协议可以参考 raft协议论文
r-nacos 接入 raft的主要逻辑:
- 基于 async-raft 库实现raft协议,主要实现网络层和存储层。在 r-nacos中存储层的状态机就是配置中心。
- 配置中心接入raft 协议的状态机,由 raft 状态机驱动更新配置中心的内容。
r-nacos一个三节点的配置中心请求处理示例:
写入:
- 客户端随机向一个节点发起一个更新配置请求
- 在请求入口层加一个raft路由判断,如果本节点是主节点则处理,否则路由到指定主节点处理
- 主节点写入请求到raft日志
- 将请求同步到其它从节点
- 如果超过半数节点写入日志成功(包含自身),则提交请求日志到状态机中,配置写入配置中心。(其它从节点的提交在下次日志同步或心跳时提交)
- 返回处理结果
请求:
- 客户端随机向一个节点发起一个查询配置请求
- 收到请求的节点和单机处理一样,直接查询本节点配置中心数据返回。
注册中心类distro协议
协议主要逻辑:
- 每个节点有全量的数据,都可提供注册信息查询服务。
- 注册中心每个节点平等,按hash划分每个节点负责的内容;节点对负责的服务可写,否则转发到对应负责的节点处理。
- 通过 grpc协议注册的服务,接收的节点直接处理。
- 一个节点更新服务实例信息后再同步给其它节点。
具体协议可以参考java nacos 的distro协议实现 。 r-nacos 和 java版主体逻辑相同,但实现的细节有些区别。
r-nacos一个三节点的注册中心请求处理示例:
http 写入:
- 客户端随机向一个节点发起一个注册服务实例请求
- 请求跳过服务路由判断,如果服务路由的节点是本节点则处理,否则路由到指定的其它节点处理
- 收到本节点负责的服务实例请求,把请求注册到注册中心中
- 返回处理结果
- 异步同步更新的数据到其它节点
grpc 写入(不路由,本节点直接处理):
- 客户端随机向一个节点发起grpc长链接
- 客户端发起一个注册服务实例请求
- 像单机一样,把请求注册到注册中心中
- 返回处理结果
- 异步同步更新的数据到其它节点
查询:
- 客户端随机向一个节点发起一个查询服务信息请求
- 收到请求的节点和单机处理一样,直接查询本节点注册中心数据返回。
为什么http的写入与grpc写入的路由逻辑不同?
因为grpc的心跳是按长链接来处理,一个客户端的链接段开,则这个链接的所用请求都失效。【高效】
然后http的实例注册是无状态的,只能通过定时器按注册时间更新实例的状态;同时注册中心中实例是按服务分类维护的。 所以http注册的实例需要按服务做路由,这样才能支持不同的节点负责不同范围的服务。【低效】
所以在注册中心使用grpc协议的性能会比http协议性能好很多。
待补充...
控制台接口
全局说明
公共对象
通用返回值
{
"success": boolean, //调用结果是否成功
"data: object, //返回对像
"code": string, //返回的错误码,在success为false时有值
"message": string , //返回的错误信息,在success为false时有值
}
通用分页对像
{
"totalCount": int, //总记录数
"list": [], //本次分页查询结果列表
}
对应的分页查询返回值为
{
"success": boolean, //调用结果是否成功
"data: {
"totalCount": int, //总记录数
"list": [], //本次分页查询结果列表
},
"code": string, //返回的错误码,在success为false时有值
"message": string , //返回的错误信息,在success为false时有值
}
特殊错误码定义
错误码 | 错误信息 | 备注 |
---|---|---|
SYSTEM_ERROR | 系统错误 | 未明确的系统错误 |
NO_LOGIN | 用户没有登陆 | 需要跳转到登陆页 |
NO_PERMISSION | 用户没有权限 | |
CAPTCHA_CHECK_ERROR | 验证码校验不通过 | |
LOGIN_LIMITE_ERROR | 用户频繁密码校验不通过被限制登陆 |
其它
重构后规范化的接口都放到/rnacos/api/console/v2/
下
接口
1. 登陆模块
登陆接口
'''
'''