- raft.h/cpp:所有对外接口的定义
- Task
- StateMachine
- Node:这里的 Node 只是对 NodeImpl 的 wrapper,所有的操作都是调用 NoteImpl 完成的
- node.h/cpp:NodeImpl 的实现,apply Task、节点管理(add_peer/remove_peer/change_peer)、snapshot、vote、append_entries 等
- replicator.h/cpp:日志复制的实现,一个 Replicator 对应一个 Follower,由 ReplicatorGroup 统一管理
- log_manager.h/cpp:日志存储相关的实现,log 格式由 log_entry.h/cpp 定义,包括了两种 log 实现:
- SegmentLogStorage:定义在 log.h/cpp 中,基于文件的日志实现,默认方式
- MemoryLogStorage:定义在 memory_log.h/cpp 中,基于内存的日志实现
- shapshot_xxx 相关:snapshot 实现,包括 SnapshotExecuto、LocalSnapshotWriter、LocalSnapshotReader、LocalSnapshotStorage 等
- raft_service.h/cpp:RPC 服务实现,一共包括 5 个 RPC:pre_vote、request_vote、append_entries、install_snapshot、timeout_now,这里只是一些简单的处理,最终还是靠调用 Node 的接口实现的。
- raft.proto:RPC 接口和消息格式定义
- node_manager.h/cpp:通常来说,我们会在一个进程中运行多组 raft(即有多个 Node 实例存在),这些所有的 Node 都监听同一个 RPC 服务端口,在收到 RPC 请求后需要根据 request 消息体中的 peer_id 找到对应的 Node 实例进行调用。
https://github.com/apache/incubator-brpc/blob/master/docs/cn/server.md#%E5%BC%82%E6%AD%A5service
braft 的实现中,都是用的异步调用。
braft 的流程都靠异步回调来驱动,其中 Closure
就是回调函数的定义,braft 中定义了各种 Closure
用于 RPC 完成后或其他步骤完成后的回调,比如 pre_vote 完成后的回调 OnPreVoteRPCDone
。
Closure
定义如下,只需要继承该类并实现 Run 方法即可,而 brpc::ClosureGuard
用于调用 Run 函数:
class PROTOBUF_EXPORT Closure {
public:
Closure() {}
virtual ~Closure();
virtual void Run() = 0;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Closure);
};
我们以 pre_vote 为例来说明,其他流程类似。pre_vote 由 VoteTimer
超时后发起,然后调用函数 NodeImpl::pre_vote()
实现 pre_vote。
NodeIMpl::pre_vote()
向其他节点发起 pre_vote RPC 请求,该调用的最后一个参数(done)类型是OnPreVoteRPCDone
- 其他节点接收到 pre_vote 请求后,会调用
NodeImpl::handle_pre_vote_request()
处理该请求并返回结果 - 当 RPC 返回后,
OnPreVoteRPCDone::Run()
函数会被回调,该函数会调用NodeImpl::handle_pre_vote_response()
处理 pre_vote 的 response。
class RaftServiceImpl : public RaftService {
public:
explicit RaftServiceImpl(butil::EndPoint addr)
: _addr(addr) {}
~RaftServiceImpl();
void pre_vote(google::protobuf::RpcController* controller,
const RequestVoteRequest* request,
RequestVoteResponse* response,
google::protobuf::Closure* done);
// ... ...
}