在微服务架构中,可能完成一个请求需要多个服务进行协作,比如一个输出商品详情页的HTTP接口,聚合服务需要查询多个通用服务,如:
- 商品基本信息:图片、标题、描述等
- 商品当前库存信息
- 商品当前价格信息
- 相关推荐商品等等
为了顺利完成如上所述的协作,微服务架构的多个服务之间需要进行相互通讯,在此场景下我们需要使用RPC(Remote Procedure Call)。
为什么微服务内部通信要用RPC,不能直接用Restful?
下图比较了RPC和REST:
RPC与Restful比较
简单来说:
- RPC:牺牲了可读性(通常为二进制编码,不可读)和通用性(需要通过IDL和私有协议定义通讯方式)压缩了通讯消息的大小 ,从而提升了通信的性能;因此多用于服务内部通信
- Restful:可读性强(JSON格式,带field名称和对应 value),通用性好(浏览器就能支持),但是消息中冗余数据较多,性能不如RPC;因此多用于服务对外通信
IDL:Interface Description Language
- 通过中立的方式来描述接口,使得跨语言跨平台之间可以通信交流,类似于桥梁作用。
- 一般提供一些通用的数据类型,只定义方法,不提供实现
GRPC作为RPC框架 ,有什么样的优势?
设计目标:
- 跨语言,易接入:GRPC支持多语言SDK
- 自由度高,可定制优化:GRPC可定制化服务发现、熔断器、负载均衡等模块,自由度高;
- 高并发性能:大并发场景下GRPC性能稳定(motan,thrift等在单机qps超过2000后延迟明显增加)
多rpc框架性能测试
其他优势:
- 基于成熟的HTTP 2.0协议,支持流式传输:一次接受和返回多个对象
- Protobuf编码将消息转换为二进制数据,时间和空间效率高
- 通过Proto文件可规范接口样式,并且有protoc工具支持自动代码生成
GRPC Over HTTP2.0
HTTP2.0简介
HTTP2.0简介:分为Headers Frame(对应1.1的header)和DATA Frame(对应1.1的body)两部分
HTTP1.1 相较于 HTTP1.0的提升点:支持长连接(keep-alive)并默认打开,一个TCP请求上可以传送多个HTTP请求和响应,避免握手和挥手造成的延迟。
HTTP2.0 相较于 HTTP1.1的提升点:多路复用+头部压缩
基本概念
- 二进制分帧:帧为HTTP2.0数据通信的最小单位;一条消息(请求/响应)可以拆分为多个帧,乱序发送,接收端可以根据帧首部的流标识重新组装
- 流:存在于连接中的虚拟通道,可以承载双向消息,每个流都有一个唯一ID
多路复用
- HTTP1.1中并发请求需要使用多个TCP链接,并且会受到浏览器的限制(单域名6-8个TCP连接)
- HTTP2.0中同域名下所有通信都在同一个TCP链接上完成,并承载任意数量的双向数据:节省了TCP的开销,提高了并发
头部压缩 HPACK
cient和server存储在一个HTTP2.0链接存续期间,共同维护一个header表
每次请求时相同的header数据不用在发送,只要发送差异即可(新增/修改):比如ua,host,cookie等
为什么GRPC基于HTTP2.0而不是基于私有协议
- HTTP2协议优势 - 成熟且经过实践检验:通用性好天然支持多设备(手机、物联网)、性能较高(相比较于HTTP1.1)、安全性较好(天然支持SSL)、支持流式数据传输;
- 私有协议除了性能好之外,其他特点都是劣势:协议需要重新设计和实践;并且对于RPC来说通用性、兼容性、可靠性比极致的性能更重要
GRPC为什么基于Protobuf而不是JSON?
PB性能更好 :消息体积小且序列化较快
消息体积更小:平均约为JSON的1/3,网络传输快
- 冗余字符少:
- json需要传输field名称,并且有{}””等冗余字符
- pb中由于双端共享proto文件,无需传输field名称,只需要传递field编号即可
- pb中一个kv的结构为Tag(1字节,field编号+数据类型)-Leg(value字符串长度,方便取值)-Value
- 编码时进行压缩:
- 整数采用varint类型,即变长整数,不固定为32字节而是根据数据的实际大小进行位数分配
- 负数采用zigzag类型,可以避免补码使用较多位数的情况
序列化和反序列化快:约为JSON的20倍
- json和xml需要读取完整字符串后进行语义分析,才能解析出对象,过程复杂 ;
- pb只需要根据Tag和Leg,进行简单的位移和运算即可解析出对象
参考
1.HTTP1.0、HTTP1.1 和 HTTP2.0 的区别
2.思考gRPC :为什么是HTTP/2
3.REST和RPC区别
4.流行的RPC框架benchmark