服务化需要搞定RPC - youngperson/study-100 GitHub Wiki
需求的开始
-
服务化的一个好处就是,不限定服务的提供方使用什么技术选型,能够实现大公司跨团队的技术解耦,但实际上,99.9%的公司的团队规模有限,技术团队人数也有限,基本是使用同一套技术体系来调用和提供服务的。
-
如果没有统一的服务框架,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框架要向调用方屏蔽各种复杂性,要向服务提供方也屏蔽各类复杂性
- 调用方感觉就像调用本地函数一样
- 服务提供方感觉就像实现一个本地函数一样来实现服务
整个RPC框架又分为client部分与server部分,负责把整个非1,2的各类复杂性屏蔽,这些复杂性就是RPC框架的职责。
-
client端又包含:序列化、反序列化、连接池管理、负载均衡、故障转移、队列管理,超时管理、异步管理等等等等职责。
-
server端包含:服务端组件、服务端收发包队列、io线程、工作线程、序列化反序列化、上下文管理器、超时管理、异步回调等等等等职责。
RPC的client端序列化
为什么需要序列化
工程师通常使用“对象”来进行数据的操作。但当需要对数据进行存储(固化存储,缓存存储)或者传输(跨进程网络传输)时,“对象”就不这么好用了,往往需要把数据转化成连续空间的二进制字节流,一些典型的场景是:
-
数据库索引的磁盘存储:数据库的索引在内存里是b+树或者hash的格式,但这个格式是不能够直接存储到磁盘上的,所以需要把b+树或者hash转化为连续空间的二进制字节流,才能存储到磁盘上
-
缓存的KV存储:redis/memcache是KV类型的缓存,缓存存储的value必须是连续空间的二进制字节流,而不能够是User对象
-
数据的网络传输:socket发送的数据必须是连续空间的二进制字节流,也不能是对象
序列化(Serialization),就是将“对象”形态的数据转化为“连续空间二进制字节流”形态数据的过程,以方便存储与传输。这个过程的逆过程叫做反序列化。
怎么序列化
-
xml(或者json)这类具有自描述特性的标记性语言
-
自己实现二进制协议来进行序列化
序列化考虑因素
-
解析效率:这个应该是序列化协议应该首要考虑的因素,像xml/json解析起来比较耗时,需要解析doom树,二进制自定义协议解析起来效率就很高
-
压缩率,传输有效性:同样一个对象,xml/json传输起来有大量的xml标签,信息有效性低,二进制自定义协议占用的空间相对来说就小多了
-
扩展性与兼容性:是否能够方便的增加字段,增加字段后旧版客户端是否需要强制升级,都是需要考虑的问题,xml/json和上面的二进制协议都能够方便的扩展
-
可读性与可调试性:这个很好理解,xml/json的可读性就比二进制协议好很多
-
跨语言:上面的两个协议都是跨语言的,有些序列化协议是与开发语言紧密相关的,例如dubbo的序列化协议就只能支持Java的RPC调用
-
通用性:xml/json非常通用,都有很好的第三方解析库,各个语言解析起来都十分方便,上面自定义的二进制协议虽然能够跨语言,但每个语言都要写一个简易的协议客户端
业内常见的序列化方式
- xml/json:解析效率,压缩率都较差;扩展性、可读性、通用性较好
- thrift:没有用过,欢迎大家补充
- protobuf:Google出品,必属精品,各方面都不错,强烈推荐,属于二进制协议,可读性差了点,但也有类似的to-string协议帮助调试问题
- CORBA:没有用过,欢迎大家补充
- mc_pack:懂的同学就懂,不懂的就不懂了,09年用过,传说各方面都超越protobuf,懂行的同学可以说一下现状