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 new_protocol.md

分布式环境中,模块数据交互协议分析 (百度brpc)的更多相关文章

  1. ZooKeeper学习第五期--ZooKeeper管理分布式环境中的数据

    引言 本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它涉及到了paxos算法.Zab协议.通信协议等相关知识,理解起来比较抽象所以还需要借助一些应用场景,来帮我们 ...

  2. 【Zookeeper系列】ZooKeeper管理分布式环境中的数据(转)

    原文地址:https://www.cnblogs.com/sunddenly/p/4092654.html 引言 本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它 ...

  3. ZooKeeper系列(5):管理分布式环境中的数据

    引言 本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它涉及到了paxos算法.Zab协议.通信协议等相关知 识,理解起来比较抽象所以还需要借助一些应用场景,来帮我 ...

  4. ZooKeeper管理分布式环境中的数据

    Reference: http://www.cnblogs.com/wuxl360/p/5817549.html 本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它 ...

  5. 分布式服务框架 Zookeeper — 管理分布式环境中的数据

    本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它涉及到了paxos算法.Zab协议.通信协议等相关知识,理解起来比较抽象所以还需要借助一些应用场景,来帮我们理解. ...

  6. ZooKeeper学习第五期--ZooKeeper管理分布式环境中的数据(转)

    转载来源:https://www.cnblogs.com/sunddenly/p/4092654.html 引言 本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它 ...

  7. 分布式服务框架 Zookeeper -- 管理分布式环境中的数据

    转自:http://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/index.html Zookeeper 分布式服务框架是 Apa ...

  8. 分布式服务框架 Zookeeper -- 管理分布式环境中的数据(转载)

    本文转载自:http://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/ Zookeeper 分布式服务框架是 Apache Had ...

  9. 分布式服务框架 Zookeeper -- 管理分布式环境中的数据--转载

    原文:http://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/ Zookeeper 分布式服务框架是 Apache Hadoop ...

随机推荐

  1. mysql基础理论

    第一节数据库管理系统概述 在www.db-engines.com/en/ 这个网站中可以看到对数据库的排名 数据库分为: 关系型数据库: mysql------mariaDB oracle 非关系型数 ...

  2. 高性能之css

    避免使用@import 有两种方式加载样式文件,一种是link元素,另一种是CSS 2.1加入@import.而在外部的CSS文件中使用@import会使得页面在加载时增加额外的延迟.虽然规则允许在样 ...

  3. php json_encode转换中文乱码

    $arr = ["a"=>'范德萨似懂非懂']; echo json_encode($arr,JSON_UNESCAPED_UNICODE);

  4. BZOJ1823 [JSOI2010]满汉全席 2-sat

    原文链接http://www.cnblogs.com/zhouzhendong/p/8125944.html 题目传送门 - BZOJ1823 题意概括 有n道菜,分别可以做成满式和汉式(每道菜只能做 ...

  5. URAL 1099 Work Scheduling (一般图最大匹配) 模板题【带花树】

    <题目链接> <转载于 >>>  > 题目大意: 给出n个士兵,再给出多组士兵之间两两可以匹配的关系.已知某个士兵最多只能与一个士兵匹配.求最多能够有多少对匹 ...

  6. Go语言为何说它优雅?-- Golang中的几个常用初始化设计

    对象池化设计: 将池对象通过Channel方式进行借出与还入,利用Go本身的特性还能实现更多限定需求.比如利用select的分支可以进行优雅的限流.超时熔断等操作.   思路:将需要池化的对象通过Ch ...

  7. springboot2.0 redis EnableCaching的配置和使用

    一.前言 关于EnableCaching最简单使用,个人感觉只需提供一个CacheManager的一个实例就好了.springboot为我们提供了cache相关的自动配置.引入cache模块,如下. ...

  8. 南阳325----zb的生日

    //重量太大,用01背包容易超时 //数据只有20组.可以用dfs搜索最优解 #include<stdio.h> ]; int maxs,n,s; void dfs(int,int); i ...

  9. csdn 站点使用

    大学时使用csdn下载软件资源,最终csdn成为一个it中很重要站点,csdn的运营方式值得思考.

  10. 【树形期望DP】BZOJ3566- [SHOI2014]概率充电器

    [题目大意] 充电器由 n-1 条导线连通了 n 个充电元件.这n-1条导线均有一个通电概率p%,而每个充电元件本身有直接被充电的概率q[i]%.问期望有多少个充电元件处于充电状态? [思路] 第一次 ...