LD is tigger forever,CG are not brothers forever, throw the pot and shine forever.
Modesty is not false, solid is not naive, treacherous but not deceitful, stay with good people, and stay away from poor people.
talk is cheap, show others the code,Keep progress,make a better result.
Survive during the day and develop at night。
关于nacos 一致性我们重点看一下类:
先看一下ap 架构:
nacos支持两种架构:一种是 CP模式,一种式AP模式:
ap:
public interface APProtocol<C extends Config, P extends RequestProcessor4AP> extends ConsistencyProtocol<C, P> {
}
类:
public abstract class RequestProcessor4AP extends RequestProcessor {
}
CP如下:
public interface CPProtocol<C extends Config, P extends RequestProcessor4CP> extends ConsistencyProtocol<C, P> {
/**
* Returns whether this node is a leader node
*
* @param group business module info
* @return is leader
*/
boolean isLeader(String group);
}
public class MetadataKey {
public static final String LEADER_META_DATA = "leader";
public static final String TERM_META_DATA = "term";
public static final String RAFT_GROUP_MEMBER = "raftGroupMember";
public static final String ERR_MSG = "errMsg";
}
请求处理:
import com.alibaba.nacos.consistency.RequestProcessor;
import com.alibaba.nacos.consistency.snapshot.SnapshotOperation;
import java.util.Collections;
import java.util.List;
/**
* log processor for cp.
*
* @author liaochuntao
*/
@SuppressWarnings("all")
public abstract class RequestProcessor4CP extends RequestProcessor {
/**
* Discovery snapshot handler It is up to LogProcessor to decide which SnapshotOperate should be loaded and saved by
* itself.
*
* @return {@link List }
*/
public List<SnapshotOperation> loadSnapshotOperate() {
return Collections.emptyList();
}
}
序列化方式采用:HessianSerializer,JacksonSerializer
snapshot :
LocalFileMeta
public class LocalFileMeta {
private final Properties fileMeta;
public LocalFileMeta() {
this.fileMeta = new Properties();
}
public LocalFileMeta(Properties properties) {
this.fileMeta = properties;
}
public LocalFileMeta append(Object key, Object value) {
fileMeta.put(key, value);
return this;
}
public Object get(String key) {
return fileMeta.getProperty(key);
}
public Properties getFileMeta() {
return fileMeta;
}
@Override
public String toString() {
return "LocalFileMeta{" + "fileMeta=" + fileMeta + '}';
}
}
Reader:
public class Reader {
private final String path;
private final Map<String, LocalFileMeta> allFiles;
public Reader(String path, Map<String, LocalFileMeta> allFiles) {
this.path = path;
this.allFiles = Collections.unmodifiableMap(allFiles);
}
public String getPath() {
return path;
}
public Map<String, LocalFileMeta> listFiles() {
return allFiles;
}
public LocalFileMeta getFileMeta(String fileName) {
return allFiles.get(fileName);
}
}
public interface SnapshotOperation {
/**
* do snapshot save operation.
*
* @param writer {@link Writer}
* @param callFinally Callback {@link BiConsumer} when the snapshot operation is complete
*/
void onSnapshotSave(Writer writer, BiConsumer<Boolean, Throwable> callFinally);
/**
* do snapshot load operation.
*
* @param reader {@link Reader}
* @return operation label
*/
boolean onSnapshotLoad(Reader reader);
}
快照写的方法:
public class Writer {
private final Map<String, LocalFileMeta> files = new HashMap<>();
private String path;
public Writer(String path) {
this.path = path;
}
public String getPath() {
return path;
}
/**
* Adds a snapshot file without metadata.
*
* @param fileName file name
* @return true on success
*/
public boolean addFile(final String fileName) {
files.put(fileName, new LocalFileMeta().append("file-name", fileName));
return true;
}
/**
* Adds a snapshot file with metadata.
*
* @param fileName file name
* @return true on success
*/
public boolean addFile(final String fileName, final LocalFileMeta meta) {
files.put(fileName, meta);
return true;
}
/**
* Remove a snapshot file.
*
* @param fileName file name
* @return true on success
*/
public boolean removeFile(final String fileName) {
files.remove(fileName);
return true;
}
public Map<String, LocalFileMeta> listFiles() {
return Collections.unmodifiableMap(files);
}
}
常见的操作:
public interface CommandOperations {
/**
* Operation and maintenance interface operation entry.
*
* @param commands commands
* @return execute success
*/
default RestResult<String> execute(Map<String, String> commands) {
return RestResultUtils.success();
}
}
常见的配置文件:
public interface Config<L extends RequestProcessor> extends Serializable {
/**
* Set the cluster node information to initialize,like [ip:port, ip:port, ip:port].
*
* @param self local node address information, ip:port
* @param members {@link Set}
*/
void setMembers(String self, Set<String> members);
/**
* members join.
*
* @param members {@link Set}
*/
void addMembers(Set<String> members);
/**
* members leave.
*
* @param members {@link Set}
*/
void removeMembers(Set<String> members);
/**
* get local node address info.
*
* @return address
*/
String getSelfMember();
/**
* get the cluster node information.
*
* @return members info, like [ip:port, ip:port, ip:port]
*/
Set<String> getMembers();
/**
* Add configuration content.
*
* @param key config key
* @param value config value
*/
void setVal(String key, String value);
/**
* get configuration content by key.
*
* @param key config key
* @return config value
*/
String getVal(String key);
/**
* get configuration content by key, if not found, use default-val.
*
* @param key config key
* @param defaultVal default value
* @return config value
*/
String getValOfDefault(String key, String defaultVal);
}
一致性协议:
public interface ConsistencyProtocol<T extends Config, P extends RequestProcessor> extends CommandOperations {
/**
* Consistency protocol initialization: perform initialization operations based on the incoming.
* Config 一致性协议初始化,根据Config 实现类
*
* @param config {@link Config}
*/
void init(T config);
/**
* Add a request handler.
*
* @param processors {@link RequestProcessor}
*/
void addRequestProcessors(Collection<P> processors);
/**
* Copy of metadata information for this consensus protocol.
* 该一致性协议的元数据信息
*
* @return metaData {@link ProtocolMetaData}
*/
ProtocolMetaData protocolMetaData();
/**
* Obtain data according to the request.
*
* @param request request
* @return data {@link Response}
* @throws Exception {@link Exception}
*/
Response getData(ReadRequest request) throws Exception;
/**
* Get data asynchronously.
*
* @param request request
* @return data {@link CompletableFuture}
*/
CompletableFuture<Response> aGetData(ReadRequest request);
/**
* Data operation, returning submission results synchronously.
* 同步数据提交,在 Datum 中已携带相应的数据操作信息
*
* @param request {@link com.alibaba.nacos.consistency.entity.WriteRequest}
* @return submit operation result {@link Response}
* @throws Exception {@link Exception}
*/
Response write(WriteRequest request) throws Exception;
/**
* Data submission operation, returning submission results asynchronously.
* 异步数据提交,在 Datum中已携带相应的数据操作信息,返回一个Future,自行操作,提交发生的异常会在CompleteFuture中
*
* @param request {@link com.alibaba.nacos.consistency.entity.WriteRequest}
* @return {@link CompletableFuture} submit result
* @throws Exception when submit throw Exception
*/
CompletableFuture<Response> writeAsync(WriteRequest request);
/**
* New member list .
* 新的成员节点列表,一致性协议自行处理相应的成员节点是加入还是离开
*
* @param addresses [ip:port, ip:port, ...]
*/
void memberChange(Set<String> addresses);
/**
* Consistency agreement service shut down .
* 一致性协议服务关闭
*/
void shutdown();
}
协议的元信息:
public final class ProtocolMetaData {
private final Map<String, MetaData> metaDataMap = new ConcurrentHashMap<>(4);
public Map<String, Map<Object, Object>> getMetaDataMap() {
return metaDataMap.entrySet().stream().map(entry -> Pair.with(entry.getKey(),
entry.getValue().getItemMap().entrySet().stream()
.collect(TreeMap::new, (m, e) -> m.put(e.getKey(), e.getValue().getData()), TreeMap::putAll)))
.collect(TreeMap::new, (m, e) -> m.put(e.getValue0(), e.getValue1()), TreeMap::putAll);
}
// Does not guarantee thread safety, there may be two updates of
// time-1 and time-2 (time-1
/**
* save target consistency protocol metadata.
*
* @param mapMap {@link Map}
*/
public void load(final Map<String, Map<String, Object>> mapMap) {
mapMap.forEach((s, map) -> {
metaDataMap.computeIfAbsent(s, MetaData::new);
final MetaData data = metaDataMap.get(s);
map.forEach(data::put);
});
}
/**
* get protocol metadata by group and key.
*
* @param group group name
* @param subKey key
* @return target value
*/
public Object get(String group, String subKey) {
if (StringUtils.isBlank(subKey)) {
return metaDataMap.get(group);
} else {
if (metaDataMap.containsKey(group)) {
return metaDataMap.get(group).get(subKey);
}
return null;
}
}
/**
* If MetaData does not exist, actively create a MetaData.
*/
public void subscribe(final String group, final String key, final Observer observer) {
metaDataMap.computeIfAbsent(group, s -> new MetaData(group));
metaDataMap.get(group).subscribe(key, observer);
}
public void unSubscribe(final String group, final String key, final Observer observer) {
metaDataMap.computeIfAbsent(group, s -> new MetaData(group));
metaDataMap.get(group).unSubscribe(key, observer);
}
@SuppressWarnings("PMD.ThreadPoolCreationRule")
public static final class MetaData {
private final Map<String, ValueItem> itemMap = new ConcurrentHashMap<>(8);
private final transient String group;
public MetaData(String group) {
this.group = group;
}
public Map<String, ValueItem> getItemMap() {
return itemMap;
}
void put(String key, Object value) {
itemMap.computeIfAbsent(key, s -> new ValueItem(group + "/" + key));
ValueItem item = itemMap.get(key);
item.setData(value);
}
public ValueItem get(String key) {
return itemMap.get(key);
}
// If ValueItem does not exist, actively create a ValueItem
void subscribe(final String key, final Observer observer) {
itemMap.computeIfAbsent(key, s -> new ValueItem(group + "/" + key));
final ValueItem item = itemMap.get(key);
item.addObserver(observer);
}
void unSubscribe(final String key, final Observer observer) {
final ValueItem item = itemMap.get(key);
if (item == null) {
return;
}
item.deleteObserver(observer);
}
}
主要讲述了nacos-ap&CP相关源码相关的分析,请大家指正~
1.链接: link