1. 回顾一下服务注册流程
当一个服务注册请求打到nacos服务器的时候,它会根据根据你这个实例的namespace, serviceName,group
信息获取到对应的service
,如果不存在就创建,然后就是进行根据你这个service里面原来的实例列表信息在加上这个新的实例信息,整合出来一个新的实例列表信息,接着就是找到一致性服务(consistencyService
)进行put
操作,这个consistencyService
会根据实例是临时节点(默认就是这个临时节点)还是永久节点选择对应的consistencyService
,其实对于临时节点对应的就是DistroConsistencyServiceImpl
,它节点之间数据同步是peer to peer
的,跟那个eureka
差不多,对于永久节点对应的是PersistentConsistencyServiceDelegateImp
l,这个里面有2个实现一个是RaftConsistencyServiceImpl
的,一个是PersistentServiceProcessor
,RaftConsistencyServiceImpl
是1.4之前版本使用的,也是我们今天要介绍的,后面这个PersistentServiceProcessor
是1.4包括以上的版本使用的(这里我们先不介绍)。 大概就是下图这个样子:
本文主要就是介绍下红框中的基于raft 协议数据同步的部分。
2. 基于raft的写操作同步
我们可以对照着上图红框部分来看看RaftConsistencyServiceImpl# put
:
@Override
public void put(String key, Record value) throws NacosException {
// 检查有没有停止
checkIsStopWork();
try {
// todo 找到这个
raftCore.signalPublish(key, value);
} catch (Exception e) {
Loggers.RAFT.error("Raft put failed.", e);
throw new NacosException(NacosException.SERVER_ERROR, "Raft put failed, key:" + key + ", value:" + value,
e);
}
}
这里没什么好说的,就是检查下状态,然后找到这个raftCore
的signalPublish
来进行存储,同步。接下来看看signalPublish
这个方法:
public void signalPublish(String key, Record value) throws Exception {
if (stopWork) {
throw new IllegalStateException("old raft protocol already stop work");
}
// 不是leader的话
if (!isLeader()) {
ObjectNode params = JacksonUtils.createEmptyJsonNode();
params.put("key", key);
params.replace("value", JacksonUtils.transferToJsonNode(value));
Map<String, String> parameters = new HashMap<>(1);
parame