服务化需要搞定RPC - youngperson/study-100 GitHub Wiki

需求的开始

  1. 服务化的一个好处就是,不限定服务的提供方使用什么技术选型,能够实现大公司跨团队的技术解耦,但实际上,99.9%的公司的团队规模有限,技术团队人数也有限,基本是使用同一套技术体系来调用和提供服务的。

  2. 如果没有统一的服务框架,RPC框架,各个团队的服务提供方就需要各自实现一套序列化、反序列化、网络框架、连接池、收发线程、超时处理、状态机等“业务之外”的重复技术劳动,造成整体的低效。所以,统一RPC框架把上述“业务之外”的技术劳动统一处理,是服务化首要解决的问题。使用统一的RPC框架”是正确的道路。

RPC的背景

什么是RPC(Remote Procedure Call Protocol),远程过程调用?先来看下什么是本地函数调用

result = Add(3,5);
Add(int a, int b){
	reurn a+b;
}

这段代码的时候,我们知道,我们传入了1,2两个入参数,调用了本地代码段中的一个Add函数,得到了result出参。此时,传入数据,传出数据,代码段在同一个进程空间里,这是本地函数调用。

那有没有办法,我们能够调用一个跨进程(所以叫“远程”,典型的,这个进程部署在另一台服务器上)的函数呢?

result = Add(3,5);	//进程A
//进程B
Add(int a, int b){
	reurn a+b;
}

两个进程约定一个协议格式,使用Socket通信,来传输【入参】【调用哪个函数】【出参】。调用方太麻烦了,每次都要关注很多底层细节。

RPC框架就是解决这个问题的,它能够让调用方“像调用本地函数一样调用远端的函数(服务)”。

RPC框架的职责

RPC框架要向调用方屏蔽各种复杂性,要向服务提供方也屏蔽各类复杂性

  1. 调用方感觉就像调用本地函数一样
  2. 服务提供方感觉就像实现一个本地函数一样来实现服务

整个RPC框架又分为client部分与server部分,负责把整个非1,2的各类复杂性屏蔽,这些复杂性就是RPC框架的职责。

  1. client端又包含:序列化、反序列化、连接池管理、负载均衡、故障转移、队列管理,超时管理、异步管理等等等等职责。

  2. server端包含:服务端组件、服务端收发包队列、io线程、工作线程、序列化反序列化、上下文管理器、超时管理、异步回调等等等等职责。


RPC的client端序列化

为什么需要序列化

工程师通常使用“对象”来进行数据的操作。但当需要对数据进行存储(固化存储,缓存存储)或者传输(跨进程网络传输)时,“对象”就不这么好用了,往往需要把数据转化成连续空间的二进制字节流,一些典型的场景是:

  1. 数据库索引的磁盘存储:数据库的索引在内存里是b+树或者hash的格式,但这个格式是不能够直接存储到磁盘上的,所以需要把b+树或者hash转化为连续空间的二进制字节流,才能存储到磁盘上

  2. 缓存的KV存储:redis/memcache是KV类型的缓存,缓存存储的value必须是连续空间的二进制字节流,而不能够是User对象

  3. 数据的网络传输:socket发送的数据必须是连续空间的二进制字节流,也不能是对象

序列化(Serialization),就是将“对象”形态的数据转化为“连续空间二进制字节流”形态数据的过程,以方便存储与传输。这个过程的逆过程叫做反序列化。

怎么序列化

  1. xml(或者json)这类具有自描述特性的标记性语言

  2. 自己实现二进制协议来进行序列化

序列化考虑因素

  1. 解析效率:这个应该是序列化协议应该首要考虑的因素,像xml/json解析起来比较耗时,需要解析doom树,二进制自定义协议解析起来效率就很高

  2. 压缩率,传输有效性:同样一个对象,xml/json传输起来有大量的xml标签,信息有效性低,二进制自定义协议占用的空间相对来说就小多了

  3. 扩展性与兼容性:是否能够方便的增加字段,增加字段后旧版客户端是否需要强制升级,都是需要考虑的问题,xml/json和上面的二进制协议都能够方便的扩展

  4. 可读性与可调试性:这个很好理解,xml/json的可读性就比二进制协议好很多

  5. 跨语言:上面的两个协议都是跨语言的,有些序列化协议是与开发语言紧密相关的,例如dubbo的序列化协议就只能支持Java的RPC调用

  6. 通用性:xml/json非常通用,都有很好的第三方解析库,各个语言解析起来都十分方便,上面自定义的二进制协议虽然能够跨语言,但每个语言都要写一个简易的协议客户端

业内常见的序列化方式

  1. xml/json:解析效率,压缩率都较差;扩展性、可读性、通用性较好
  2. thrift:没有用过,欢迎大家补充
  3. protobuf:Google出品,必属精品,各方面都不错,强烈推荐,属于二进制协议,可读性差了点,但也有类似的to-string协议帮助调试问题
  4. CORBA:没有用过,欢迎大家补充
  5. mc_pack:懂的同学就懂,不懂的就不懂了,09年用过,传说各方面都超越protobuf,懂行的同学可以说一下现状