首页 > 体育花边 > 造轮子系列之Protobuf
2019
05-08

造轮子系列之Protobuf

作为一个法式猿,对造轮子这工作可以说是情有独钟,几乎法式猿心坎都存在一个幻想是往将开源的技巧都实现一遍,所有从本篇开端,我会开一个造轮子系列。


媒介

起首,看看这个,想必大师对下面这种简历看得比拟多了吧?

  • 精晓JAVA,Python,谙练把握C++
  • 精晓Redis,Memcached,Mysql
  • 精晓Nginx设置装备摆设,模块开辟
  • 精晓Kafka,ActiveMQ 等新闻队列
  • 精晓常用数据构造和算法
  • 精晓收集编程,多线程编程技巧,高机能办事器技巧
  • 精晓tcp/ip协定栈,熟习内核收集子体系代码
  • 精晓nginx代码及模块开辟

上面每一条都涉及很多多少轮子,每一个都是精晓,假如真能做到。那这小我可以说是码农中的战役机。

那我们此刻目的就是往做这个战役机。而这个方式,就是本身往造轮子,造的目标不是为了在项目中应用本身造的轮子,而是为了往懂得轮子的结构,然后本身脱手往领会造轮子的进程。


后真个轮子们

说起后真个轮子们,大师都可以说出一年夜串来,我们年夜致来数一数啊。

  • 抗在最前面的:LVS,F5,HAProxy这类负载平衡
  • 接下来有Nginx,Apache,Lighttpd这类Http办事
  • http办事后则是各类容器,安排着我们的营业逻辑
  • 存储这边有Redis,Memcached这一类KV存储器缓和存体系
  • 假如是多机安排,确定还有Kafka,ActiveMQ这种负责解耦的新闻队列
  • 为了实现集群通讯,确定少不了Thrift这种RPC框架和Protobuf这种序列化技巧
  • 再高端点,到了散布式范畴了,就是更多的轮子了。。zookeeper、raft等等
  • 还有年夜数据系列hadoop。spark。。。。。

本文先开端我们的第一个轮子,办事器通讯须要用的数据序列化反序列技巧:protobuf。


基本轮子:protobuf

讲基本前,先附上一张极客时光中的一个技巧须要从哪些角度来讲的图片,本文也会尽可能从这些个方面来讲。

造轮子系列之Protobuf - 第1张  | 长沙娱乐资讯博客-风影娱乐八卦资讯

  • 利用角度
  • 题目:”干什么用“
  • 技巧规范:”怎么用“
  • 最佳实践:”怎么能用好“
  • 市场利用趋向:“谁用,用在哪”
  • 设计角度
  • 目的:“做到什么”
  • 实现道理:“怎么做到”
  • 好坏局限:“做得怎么样”
  • 演进趋向:“将来若何”

正文

Protocol buffers

从利用角度看protobuf是干什么用的?

序列化数据用的?什么时辰须要序列化?当数据须要存储或者收集传输的时辰。为什么呢?

在存储或者传输的时辰,我们能看到都是一些二进制数据,即010101……的bit。

假设我们看的一个对象是:

Struct myData {

Int a;

Int b;

}

data = myData {

a:1,

b:2,

}

那我们在收集上收到是一个字节省,我们为了可以或许从字节省中恢复出数据 data,我们要做的工作是:

  1. 准确辨认出data在字节省中开端和停止的地位
  2. 辨认出a的值,辨认出b的值

一个可能的字节省协定就是:

造轮子系列之Protobuf - 第2张  | 长沙娱乐资讯博客-风影娱乐八卦资讯

刚开端是8bit标明后续数据是哪个构造,然后是两个4字节表现a和b。


留意!!!!!上面做出上面这个假设,有几点是我们默认的:

  1. 我们以为字节省开端先是8bit标明是哪个数据构造,此处是myData(ps:分歧构造之间编号分歧)
  2. 最多可以或许支撑2^8种构造
  3. 通信两边都须要拿到myData的界说文件

以下是一个上面实现的示例代码:

造轮子系列之Protobuf - 第3张  | 长沙娱乐资讯博客-风影娱乐八卦资讯

可以看到在go中很轻易就实现了我们的一个数据构造的序列化反序列化。

设计角度,做到什么?

上面我们只是实现了一个最简略的实现了一个序列化方式,下面我们来看假如要实现一个出产情况中的序列化协定,须要做到哪几点。

  1. 通用性:说话、平台无关
  2. 高机能:序列化和反序列化都要快
  3. 高紧缩:序列化后数据尽可能小,小就意味着收集传输数据少
  4. 兼容性:数据构造转变了,也可以或许支撑新老版本

下面我们带着这些目的来从利用角度来看下”怎么用“

这个就是官方文档了https://developers.google.com/protocol-buffers/docs/gotutorial,里面有具体的阐明,别的我本身给了一份应用示例:https://github.com/zhuanxuhit/go-in-practice/tree/master/wheel/protobuf/v2

讲完应用下面就是设计角度:若何做到的?

起首我们看前文我们本身实现的简略单纯序列化、反序列方式,我们对每个构造进行编码,然后在头部写上该构造是啥,然后后面就是构造中每个字段的具体值,接着我们写了序列化器的目的是:简略单纯、高效、兼容,下面我们从这几个方面来看protobuf有什么改良的处所。

先来个小插曲,protobuf全称是Protocol buffers,此中buffers点名了应用上很是主要的一个点,即我们在反序列化的一段二进制数据的时辰,我们要将其先读进到buffer中,然后再辨认出单个数据构造的开首和结尾,最后才干准确的反序列化出来。

前面我们设计的时辰,还在头部对数据构造进行了编码,那为了可以或许做到更高效,数据更小,我们是否可以把这个头也往失落呢?

当然是可以的,于是我们的构造就变为了只有对应的字段值了,这么做的一个条件是:!!我们必需明白知道我们辨认出来二进制数据,其对应的具体是哪个数据构造。!!

此刻我们往失落告终构描写,那怎么可以或许做到更小呢?譬如同样是int64,1 和 1<<32没需要都用8字节来表现,譬如我们可以先对数据类型做一个编码,然后紧随着后续应用的bit,再随着真正的数据。

造轮子系列之Protobuf - 第4张  | 长沙娱乐资讯博客-风影娱乐八卦资讯

每个部门分辨用几个bit来表现呢?

  • 数据类型:依据支撑的类型进行编码,假如总共能支撑16种类型,那就是4bit
  • 后续有用字节:这个比拟难办,因为我们不断定数据巨细,我们就无法固定bit来表现。

那一个解决方式就是:我们往失落有用字节的字段,我们把这个是否有更大都据信息编码进数据自己中,示意图如下:

造轮子系列之Protobuf - 第5张  | 长沙娱乐资讯博客-风影娱乐八卦资讯

解决了编码int类型的字段后,假如碰到string类型呢?这种类型起首也是数据类型描写,接着应当如果编码后续有用字节,这是一个int,这可以采取上面的方式来编码,再随着就是有用数据了。

造轮子系列之Protobuf - 第6张  | 长沙娱乐资讯博客-风影娱乐八卦资讯

以上就是protobuf在编码数据时采取编码方法的重要思惟,具体可以看https://developers.google.com/protocol-buffers/docs/encoding。

今朝protobuf支撑的数据类型

造轮子系列之Protobuf - 第7张  | 长沙娱乐资讯博客-风影娱乐八卦资讯

上面有个主张的对于有符号数,我们要零丁处置下,由于有符号数的最高位是经由过程0,1来表现正负的,可是上面编码中最高位却用来表现是否有后续数据了,所以我们要经由过程ZigZag 编码将有符号转换为无符号。

道理很简略,就是经由过程下面的编码方法:

造轮子系列之Protobuf - 第8张  | 长沙娱乐资讯博客-风影娱乐八卦资讯

解决了编码后,我们来看最后一个题目:兼容性。

假如我们转变了数据构造:新增或者删除了字段怎么办???

这个也好解决,那我们就给所有字段加上编号,经由过程字段来表现这个数据是构造体中哪个字段,protobuf在设计上编码方法如下:

图片来自:高效的数据紧缩编码方法 Protobuf

从上图中tag的编码,我们可以发明,假如field_num > 16的话,tag编码出来会应用跨越1字节,所有对于我们经常应用的字段,建议将其编码到0-15,削减tag位数。

实现道理小结

下面我们对上面先容的实现道理做个小结

高效:变长编码,非自描写

兼容:对filed进行编码

下面我们再从利用角度讲下 protobuf 的最佳实践和市场利用趋向。

protobuf刚开端设计出来重要是为懂得决接口兼容性题目,今朝是重要用在内部办事之间RPC挪用和传递数据,今朝时辰用protobuf作为序列化的rpc框架有gRPC,这也是后续我们会先容的。

最后我们从设计角度来看下protobuf的好坏局限和演进趋向。

长处

protobuf最年夜的长处就是前后兼容性,已经安排的应用老数据格局的办事,即使接口进级了也可以持续应用,然后就是机能,当然是快了,具体可以看 序列化 / 反序列化机能

毛病

比拟较json来说,可读性差,特殊是在调试阶段,比拟较json我们无法清楚的知道输进和输出。


最后

总结下本文

  1. Protobuf设计之初重要是为懂得决兼容性题目,实现上是对每个字段进行编号,当碰到不存在的字段时,则疏忽失落。
  2. Protobuf为了可以或许做到高机能,在编码时采取了Tag – Value (Tag – Length – Value)的方法,使序列化后的数据更紧凑
  3. Protobuf为了可以或许做到高机能,丢弃了自描写信息,即我们只拿到数据,而没有拿到proto文件,我们是无法反序列数据的
  4. Protobuf供给了一套编译东西,可以或许天生分歧说话的数据序列化、反序列化方式,极年夜的进步了易用性

预告

下一篇我们会先容grpc,来看下rpc框架中是怎么应用protobuf的。

参考

高效的数据紧缩编码方法 Protobuf

官方文档

,

最后编辑:
作者:nokia105
这个作者貌似有点懒,什么都没有留下。

留下一个回复

你的email不会被公开。