Raft
什么是Raft
Section titled “什么是Raft”请阅读 zeze/Zeze/Raft/下的Raft.mhtml,raft.pdf,OngaroPhD.pdf。 这里不再重复。
Zeze.Raft.StateMachine
Section titled “Zeze.Raft.StateMachine”应用数据定义在这里。
Zeze.Raft.Log
Section titled “Zeze.Raft.Log”定义应用数据(StateMachine)修改操作。 每次操作对应一个Log子类。
Zeze.Raft.Raft.AppendLog
Section titled “Zeze.Raft.Raft.AppendLog”把修改操作日志(Log)添加到Raft日志队列中。 当AppendLog方法返回时,表示操作已经被成功处理。
Zeze.Raft.Agent
Section titled “Zeze.Raft.Agent”应用的客户端管理类。 自动切换Raft-Leader变更,自动重发请求。
Zeze.Raft.RaftRpc
Section titled “Zeze.Raft.RaftRpc”自定义应用访问协议基类。 当协议用zeze生成的时候,在协议定义里面指名 base=“Zeze.Raft.RaftRpc”。 建议每个RaftRpc对应一条Log。
- ResultCode==RaftApplied:Raft发现请求是重发的,但是已经 成功处理过。
- ResultCode==RaftExpired:请求过期了,无法判断是否被成功 处理。
// 注意,以下例子没有处理多线程问题。// 应用数据class MyStateMachine : Zeze.Raft.StateMachine{ public long Count; // 操作日志 class AddCount : Zeze.Raft.Log { public AddCount(IRaftRpc req) : base(req) { } public override void Apply(RaftLog holder, StateMachine stateMachine) { (stateMachine as MyStateMachine).Count += 1; } }
// 应用操作接口。这里传入的是下面定义的AddCount网络协议。 public void AddCount(IRaftRpc request) { Raft.AppendLog(new AddCount(request)); }
// 需要实现的接口 // 参考Zeze.Raft.Test.TestStateMachine public override void LoadSnapshot(string path) { }
public override bool Snapshot(string path, out long LastIncludedIndex, out long LastIncludedTerm) { }
public MyAppStateMachine() { // 注册Log工厂。 AddFactory(new AddCount(null).TypeId, () => new AddCount(null)); }}
// 增加Count计数的协议public sealed class AddCount : RaftRpc<EmptyBean, EmptyBean>{ public readonly static int ProtocolId_ = Bean.Hash32(typeof(AddCount).FullName); public override int ModuleId => 0; public override int ProtocolId => ProtocolId_;}
// 服务器创建Raft实例 var configFileName = "raft.xml"; var config = Zeze.Raft.RaftConfig.Load(configFileName); var nodeName = config.Name; // 所有的raft-node共享一个配置文件时, // 需要通过参数指定启动的node名字。
var stateMachine = new MyAppStateMachine(); var raft = new Raft(stateMachine, nodeName, config);
// 服务器协议处理 long ProcessAddCountRequest(Protocol p) { var r = p as AddCount; stateMachine.AddCount(r); }
// 客户端创建Agent var agent = new Agent("MyRaftApp.Agent", config); agent.Client.AddFactoryHandle(new AddCount().TypeId, new Net.Service.ProtocolFactoryHandle() { Factory = () => new AddCount(), });
// 客户端发送网络请求 var req = new AddCount(); agent.SendForWait(req).Task.Wait(); if (req.Result.ResultCode == ) ...