json 这种直观的消息协议的可读性非常棒,但是它的缺点也很明显,有太多的冗余信息.济南达内的小编说啊,比如每个字符串都使用双引号来界定边界,key/value 之间必须有冒号分割,对象之间必须使用大括号分割等等.这些还只是冗余的小头,最大的冗余还在于连续的多条 json 消息即使结构完全一样,仅仅只是 value 的值不一样,也需要发送同样的 key 字符串信息.
消息的结构在同一条消息通道上是可以复用的,比如在建立链接的开始 RPC 客户端和服务器之间先交流协商一下消息的结构,后续发送消息时只需要发送一系列消息的 value 值,接收端会自动将 value 值和相应位置的 key 关联起来,形成一个完成的结构消息.在 Hadoop 系统中广泛使用的 avro 消息协议就是通过这种方式实现的,在 RPC 链接建立之处就开始交流消息的结构,后续消息的传递就可以节省很多流量.
消息的隐式结构一般是指那些结构信息由代码来约定的消息协议,在 RPC 交互的消息数据中只是纯粹的二进制数据,由代码来确定相应位置的二进制是属于哪个字段.比如下面的这段代码如果纯粹看消息内容是无法知道节点消息内容中的哪些字节的含义,它的消息结构是通过代码的结构顺序来确定的.这种隐式的消息的优点就在于节省传输流量,它完全不需要传输结构信息.
消息压缩如果消息的内容太大,就要考虑对消息进行压缩处理,这可以减轻网络带宽压力.但是这同时也会加重 CPU 的负担,因为压缩算法是 CPU 计算密集型操作,会导致操作系统的负载加重.所以,最终是否进行消息压缩,一定要根据业务情况加以权衡.
如果确定压缩,那么在选择压缩算法包时,务必挑选那些底层用 C 语言实现的算法库,因为 Python 的字节码执行起来太慢了.比较流行的消息压缩算法有 Google 的 snappy 算法,它的运行性能非常好,压缩比例虽然不是最优的,但是离最优的差距已经不是很大.阿里的 SOFA RPC 就使用了 snappy 作为协议层压缩算法.
流量的极致优化开源的流行 RPC 消息协议往往对消息流量优化到了极致,它们通过这种方式来打动用户,吸引用户来使用它们.比如对于一个整形数字,一般使用 4 个字节来表示一个整数值.
但是经过研究发现,消息传递中大部分使用的整数值都是很小的非负整数,如果全部使用 4 个字节来表示一个整数会很浪费.所以就发明了一个类型叫变长整数varint.数值非常小时,只需要使用一个字节来存储,数值稍微大一点可以使用 2 个字节,再大一点就是 3 个字节,它还可以超过 4 个字节用来表达长整形数字.
其原理也很简单,就是保留每个字节的最高位的 bit 来标识是否后面还有字节,1 表示还有字节需要继续读,0 表示到读到当前字节就结束.
那如果是负数该怎么办呢?-1 的 16 进制数是 0xFFFFFFFF,如果要按照这个编码那岂不是要 6 个字节才能存的下.-1 也是非常常见的整数啊.
于是 zigzag 编码来了,专门用来解决负数问题.zigzag 编码将整数范围一一映射到自然数范围,然后再进行 varint 编码.
zigzag 将负数编码成正奇数,正数编码成偶数.解码的时候遇到偶数直接除 2 就是原值,遇到奇数就加 1 除 2 再取负就是原值.
小结现在我们知道了 RPC 消息结构的设计原理,遵循这些基本方法,就可以创造出一个又一个不同的消息协议.
以上就是济南达内给大家做的内容详解,更多关于IT知识的学习,请继续关注济南达内