分布式环境中,模块数据交互协议分析 (百度brpc)
1. 背景
之前听到同事说,要为自己的模块考虑写个数据协议。今天有空想了一下。写出来,方便后续使用。
开源代码brpc中可以支持多种协议,nshead、redis、mongo等20多种协议。
2. 什么是数据交互协议?
这里说的协议,不是tcp/ip这些网络协议。
在分布式环境中,我们需要将模块的数据通过网络bit流传给上、下游模块,就会涉及到数据完整性、正确性校验。
为了能够校验数据,就需要定义数据交换协议。
3. 代码brpc中的实现
每种协议类型,都需要实现自己的parser类,进行消息的验证。
3.1 bprc 中nshead协议的校验
nshead_t 结构体
static const unsigned int NSHEAD_MAGICNUM = 0xfb709394; //特殊数字
struct nshead_t {
unsigned short id;
unsigned short version;
unsigned int log_id;
char provider[16];
unsigned int magic_num;
unsigned int reserved;
unsigned int body_len; //实际传输的包体长度
};
校验过程:magic_num是否正确,是否包体超长,是否包体收到数据不足等。
ParseResult ParseNsheadMessage(butil::IOBuf* source,
Socket*, bool /*read_eof*/, const void* /*arg*/) {
char header_buf[sizeof(nshead_t)];
const size_t n = source->copy_to(header_buf, sizeof(header_buf));
if (n < offsetof(nshead_t, magic_num) + 4) {
return MakeParseError(PARSE_ERROR_NOT_ENOUGH_DATA);
}
const void* dummy = header_buf + offsetof(nshead_t, magic_num);
const unsigned int magic_num = *(unsigned int*)dummy;
if (magic_num != NSHEAD_MAGICNUM) {
RPC_VLOG << "magic_num=" << magic_num
<< " doesn't match NSHEAD_MAGICNUM=" << NSHEAD_MAGICNUM;
return MakeParseError(PARSE_ERROR_TRY_OTHERS);
}
if (n < sizeof(nshead_t)) {
return MakeParseError(PARSE_ERROR_NOT_ENOUGH_DATA);
}
const nshead_t* nshead = (const nshead_t *)header_buf;
uint32_t body_len = nshead->body_len;
if (body_len > FLAGS_max_body_size) {
return MakeParseError(PARSE_ERROR_TOO_BIG_DATA);
}
else if (source->length() < sizeof(header_buf) + body_len) {
return MakeParseError(PARSE_ERROR_NOT_ENOUGH_DATA);
}
policy::MostCommonMessage* msg = policy::MostCommonMessage::Get();
source->cutn(&msg->meta, sizeof(header_buf));
source->cutn(&msg->payload, body_len);
return MakeMessage(msg);
}
3.2 bprc 中redis协议的校验
先看看redis中的协议,比如下面主从复制时需要的select db的情形。表示有2行(*2),第一行len:6, vak:SELECT, 第二行len:2, val:10
*2\r\n
$6\r\n
SELECT\r\n
$2\r\n
10\r\n
校验过程:字符串处理,switch ...case...
bool RedisReply::ConsumePartialIOBuf(butil::IOBuf& buf, butil::Arena* arena) {
// Notice that all branches returning false must not change `buf'.
const char* pfc = (const char*)buf.fetch1();
if (pfc == NULL) {
return false;
}
const char fc = *pfc; // first character
switch (fc) {
case '-': // Error "-<message>\r\n"
case '+': { // Simple String "+<string>\r\n"
......
4. 如果要自己实现一种协议
可以学习上面的两种情况:
(1) nshead 使用特殊magic数组, bodylen,body
(2) redis 使用val_len, val
这也是
通用的套路,len + value限定了一个变量。
当然可以加一些crc校验和,等其他条件。
5. 参考:
分布式环境中,模块数据交互协议分析 (百度brpc)的更多相关文章
- ZooKeeper学习第五期--ZooKeeper管理分布式环境中的数据
引言 本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它涉及到了paxos算法.Zab协议.通信协议等相关知识,理解起来比较抽象所以还需要借助一些应用场景,来帮我们 ...
- 【Zookeeper系列】ZooKeeper管理分布式环境中的数据(转)
原文地址:https://www.cnblogs.com/sunddenly/p/4092654.html 引言 本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它 ...
- ZooKeeper系列(5):管理分布式环境中的数据
引言 本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它涉及到了paxos算法.Zab协议.通信协议等相关知 识,理解起来比较抽象所以还需要借助一些应用场景,来帮我 ...
- ZooKeeper管理分布式环境中的数据
Reference: http://www.cnblogs.com/wuxl360/p/5817549.html 本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它 ...
- 分布式服务框架 Zookeeper — 管理分布式环境中的数据
本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它涉及到了paxos算法.Zab协议.通信协议等相关知识,理解起来比较抽象所以还需要借助一些应用场景,来帮我们理解. ...
- ZooKeeper学习第五期--ZooKeeper管理分布式环境中的数据(转)
转载来源:https://www.cnblogs.com/sunddenly/p/4092654.html 引言 本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它 ...
- 分布式服务框架 Zookeeper -- 管理分布式环境中的数据
转自:http://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/index.html Zookeeper 分布式服务框架是 Apa ...
- 分布式服务框架 Zookeeper -- 管理分布式环境中的数据(转载)
本文转载自:http://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/ Zookeeper 分布式服务框架是 Apache Had ...
- 分布式服务框架 Zookeeper -- 管理分布式环境中的数据--转载
原文:http://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/ Zookeeper 分布式服务框架是 Apache Hadoop ...
随机推荐
- outlook邮件中样式问题
目前要做一个定时发送邮件的功能,邮件的大致内容布局如下: HTML中 在QQ邮件中,可以进行正常显示. 在outlook网页版,也可以正常显示, outlook客户端 但是到了客户端就会出现很多很神奇 ...
- Python 输出有颜色的字体
https://www.cnblogs.com/hellojesson/p/5961570.html
- HTML自定义滚动条(仿网易邮箱滚动条)转载
它是使用CSS中的伪元素来实现的,主要由以下三个来完成: 1. -webkit-scrollbar:定义滚动条的样式,如长宽. 2. -webkit-scrollbar-thumb:定义滚动条上滑块的 ...
- 查看当前的app运行的是哪个Activity
1.确认手机连接了adb-->检查方式:adb devices 2.手机运行任意app,随意进入一个页面 3.此时cmd运行:adb shell "dumpsys window | g ...
- quratz线程
1.线程 在 Quartz 中,有两类线程,Scheduler 调度线程和任务执行线程,其中任务执行线程通常使用一个线程池维护一组线程. 2.调度线程 下面说明两种调度线程: Scheduler 调度 ...
- MATLAB的一些使用的快捷键整理
1.用TAB键可以实现缩进,怎么缩进和取消缩进呢? 在使用脚本编写matlab的程序时,我们通过选中需要的程序,按下tab键就能缩进整个程序.同样的,当我们需要取消缩进时,我们的快捷方法就是:shif ...
- HDU 3594 Cactus (强连通+仙人掌图)
<题目链接> <转载于 >>> > 题目大意: 给你一个图,让你判断他是不是仙人掌图. 仙人掌图的条件是: 1.是强连通图. 2.每条边在仙人掌图中只属于一个 ...
- numpy 用于图像处理
1. 转换为灰度图 灰度图的数据可以看成是二维数组,元素取值为0 ~ 255,其中,0为黑色,255为白色.从0到255逐渐由暗色变为亮色. 灰度图转换(ITU-R 601-2亮度变换): L = R ...
- 002.Oracle安装部署-ASM
一 环境准备 图形界面:略 安装包: linux.x64_11gR2_database_1of2.zip linux.x64_11gR2_database_2of2.zip 二 安装ASM-Oracl ...
- 记录一个chrome 65渲染的bug
前段时间发现一个chrome 65+的BUG(chrome已更新到66,BUG仍然存在),一个元素同时使用了以下样式(失去焦点和css3的Z轴平移0deg),渲染异常 /*bug style*/ fi ...