1. 准备阶段
准备5台机器搭建新Nacos集群,并跨多个可用区部署,如下:
E区:172.18.76.229、172.18.76.230(断网区)
F区:172.18.185.171、172.18.185.185(多泳道区)
D区:172.18.48.1
准备1~2台机器,运行测试程序:
D区:172.18.48.2、172.18.48.5
测试Nacos集群在某一可用区下所有节点宕机情况下,是否仍能正常对外提供服务,测试程序(release分支):
https://gitlab.huolala.cn/group-risk/group-risk-engine/dubbo-demo.git
Nacos关闭双写
在2.0.3版本默认开启双写,只要nacos集群其中一个节点挂掉,剩余节点如果不将这个节点从地址列表中移除,只要重启便会出现服务降级;另外在并发部署的情况下,也有可能出现服务降级。
关闭双写会关闭运行中服务降级的入口,所以2.x服务运行稳定后一定要关闭双写。否则在一定的场景下可能出现服务降级导致部分节点不可用。
-
Nacos查看节点监控:
curl -X GET 'localhost:8848/nacos/v1/ns/upgrade/ops/metrics'
-
关闭双写:
curl -X PUT 'localhost:8848/nacos/v1/ns/operator/switches?entry=doubleWriteEnabled&value=false'
-
重启服务
Nacos服务器监听某端口,方便重启
#!/bin/bash
PORT=8080
# 使用nc监听指定端口,并设置-k选项以保持监听状态
echo "Listening on port $PORT..."
nc -l -k $PORT | while IFS= read -r line; do
echo "$(date +"%Y-%m-%d %H:%M:%S")" "received: $line"
if [ "$line" = "startup" ]; then
sh /home/data/nacos/bin/startup.sh -p embedded
fi
if [ "$line" = "shutdown" ]; then
sh /home/data/nacos/bin/shutdown.sh
fi
done
Nacos服务列表、节点列表查看脚本(新集群未配置域名或SLB,无法通过控制台查看):
#!/bin/bash
services=false
nodes=false
#ip=localhost
ip=172.18.48.1
for arg in "$@"
do
if [ "$arg" = "services" ]; then
services=true
elif [ "$arg" = "nodes" ]; then
nodes=true
fi
done
# echo $services
# echo $nodes
# 登录
login_resp=$(curl --location "http://$ip:8848/nacos/v1/auth/users/login" \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'username=nacos' \
--data-urlencode 'password=nacos')
access_token=$(echo "$login_resp" | jq -r '.accessToken')
echo "accessToken: $access_token"
echo "=================================================================================="
if [ "$services" = true ]; then
# 服务列表
services_resp=$(curl --location "http://$ip:8848/nacos/v1/ns/catalog/services?hasIpCount=true&withInstances=false&pageNo=1&pageSize=300&serviceNameParam=&groupNameParam=&accessToken=$accessToken&namespaceId=")
service_list=$(echo "$services_resp" | jq -r '.serviceList')
echo "serviceList: $service_list"
echo "=================================================================================="
fi
if [ "$nodes" = true ]; then
# 集群节点列表
nodes_resp=$(curl --location "http://$ip:8848/nacos/v1/core/cluster/nodes?withInstances=false&pageNo=1&pageSize=300&keyword=&accessToken=$accessToken&namespaceId=")
node_list=$(echo "$nodes_resp" | jq -r '.data')
echo "nodeList: $node_list"
echo "=================================================================================="
fi
2. 测试
2.1 简单测试
-
注册服务实例5个,服务监听2个。运行脚本查看Nacos服务注册情况
curl --location 'http://172.18.48.2:8080/test/async' \ --header 'Content-Type: application/json' \ --data '{ "PROVIDER_REGISTER": { "host": "127.0.0.1:8080", "basePort": 9000, "baseDubboPort": 19000, "instanceNum": 5 }, "CONSUMER_DISCOVERY": { "host": "127.0.0.1:8080", "basePort": 8000, "baseDubboPort": 18000, "instanceNum": 2 } }'
-
开启2个线程发起RPC调用5min,在此期间下线E区所有节点,观察RPC调用是否正常(测试断网过程中,RPC情况)
curl --location 'http://172.18.48.2:8080/test/async' \ --header 'Content-Type: application/json' \ --data '{ "RPC": { "consumers": "localhost:8001,localhost:8002", "threadNum": 2, "duration": 300 } }'
-
再次注册服务实例5个,服务监听2个,运行脚本查看注册情况(测试断网后,服务注册情况)
curl --location 'http://172.18.48.2:8080/test/async' \ --header 'Content-Type: application/json' \ --data '{ "PROVIDER_REGISTER": { "host": "127.0.0.1:8080", "basePort": 9010, "baseDubboPort": 19010, "instanceNum": 5 }, "CONSUMER_DISCOVERY": { "host": "127.0.0.1:8080", "basePort": 8010, "baseDubboPort": 18010, "instanceNum": 2 } }'
-
开启4个线程发起RPC调用5min,在此期间启动E区所有Nacos节点,观察RPC调用是否正常,(测试断网后、网络恢复过程中、网络恢复后,RPC情况)
curl --location 'http://172.18.48.2:8080/test/async' \ --header 'Content-Type: application/json' \ --data '{ "RPC": { "consumers": "localhost:8001,localhost:8002,localhost:8011,localhost:8012", "threadNum": 4, "duration": 300 } }'
2.2 测试流程
2.3 主节点选举
-
查看主节点
-
RPC进行时,断掉主节点,继续查看返回结果
3. 发现问题
-
Nacos集群在某些节点下线一段时间后,再次上线这些节点,Raft主节点内存会骤升至一个高度(主节点内存增加量 ≈ 下线节点启动前后内存变化量)
-
在Nacos集群某些节点下线重启后,服务state显示为“UP”,但实际不可用,无法正常注册服务到该节点
-
在Nacos集群某些节点下线后,再发送服务注册或服务注销请求,会出现部分服务注册不上或注销不了的情况(应该是发送到了宕机的节点上):
再次上线这些节点后,实例会自动注册进Nacos集群:
-
额额额
4. 解决方案
问题1:重启该内存占用过高的主节点
问题2:关闭Nacos集群双写(已解决该问题)
问题3:SLB健康检查机制可以解决访问宕机节点问题