侵删,仅供参考学习
braft的官方文档
个人建议,由于braft的说明文档并没有那么友好,可以先看一遍jraft的文档,两个的大致思路和一些变量名称是一样的,这样对理解braft的帮助会大一些。
braft 本身并不提供server功能, 你可以将braft集成到包括brpc在内的任意编程框架中,本文主要是阐述如何在分布式Server中使用braft来构建高可用系统。具体业务如何实现一个Server,本文不在展开。
Example
server-side code of Counter(服务端代码的例子)
注册并且启动Server
braft需要运行在具体的brpc server里面你可以让braft和你的业务共享同样的端口, 也可以将braft启动到不同的端口中.
brpc允许一个端口上注册多个逻辑Service, 如果你的Service同样运行在brpc Server里面,你可以管理brpc Server并且调用以下任意一个接口将braft相关的Service加入到你的Server中。这样能让braft和你的业务跑在同样的端口里面, 降低运维的复杂度。如果对brpc Server的使用不是非常了解, 可以先查看wiki页面.
注意: 如果你提供的是对外网用户暴露的服务,不要让braft跑在相同的端口上。
//将raft服务附加到| server |(自己的服务端),这使raft服务与用户服务共享相同的侦听地址。
//注意:目前,我们仅允许使用特定的侦听地址启动备用服务器,如果要从一个范围端口启动该服务器,则行为是不确定的。
//成功返回0,否则返回-1。
int add_service(brpc::Server* server, const butil::EndPoint& listen_addr);
int add_service(brpc::Server* server, int port);
int add_service(brpc::Server* server, const char* const butil::EndPoint& listen_addr);
- 调用这些接口之前不要启动server, 否则相关的Service将无法加入到这个server中. 导致调用失败.
- 启动这个server的端口需要和add_service传入的端口一致, 不然会导致这个节点无法正常收发RPC请求.
实现业务状态机
你需要继承braft::StateMachine并且实现里面的接口
//将raft服务附加到| server |(自己的服务端),这使raft服务与用户服务共享相同的侦听地址。
//注意:目前,我们仅允许使用特定的侦听地址启动备用服务器,如果要从一个范围端口启动该服务器,则行为是不确定的。
//成功返回0,否则返回-1。
int add_service(brpc::Server* server, const butil::EndPoint& listen_addr);
int add_service(brpc::Server* server, int port);
int add_service(brpc::Server* server, const char* const butil::EndPoint& listen_addr);
#include <braft/raft.h>
//注意:不需要所有接口都是线程安全的,它们是按顺序调用的,就是说每个方法都会阻塞之后的所有方法。
class YourStateMachineImple : public braft::StateMachine {
protected:
// on_apply是*必须*实现的
// on_apply会在一条或者多条日志被多数节点持久化之后调用, 通知用户将这些日志所表示的操作应用到业务状态机中.
// 通过iter, 可以从遍历所有未处理但是已经提交的日志, 如果你的状态机支持批量更新,可以一次性获取多
// 条日志提高状态机的吞吐.
//
void on_apply(braft::Iterator& iter) {
// 提交了一批任务,必须通过| iter |处理。
for (; iter.valid(); iter.next()) {
// 该保护措施有助于异步调用iter.done()->Run(),避免回调阻塞StateMachine。
braft::AsyncClosureGuard closure_guard(iter.done());
// 从iter.data()解析出操作语句,并执行
// op = parse(iter.data());
// result = process(op)
// 跟踪日志是为了帮助您了解此StateMachine的工作方式。
// 可以在性能敏感的服务器中删除这些日志。
LOG_IF(INFO, FLAGS_log_applied_task)
<< "Exeucted operation " << op
<< " and the result is " << result
<< " at log_index=" << iter.index();
}
}
// 当这个braft节点被shutdown之后, 当所有的操作都结束, 会调用on_shutdown, 来通知用户这个状态机不再被使用。
// 这时候你可以安全的释放一些资源了.
virtual void on_shutdown() {
// 清理您想要清理的资源
}
iterator
通过braft::iterator你可以遍历从所有有的任务
class Iterator {
// 移至下一个任务。
void next();