前言
所有内容将会围绕下面的模型图进行阐述
HTTP 协议
对于 HTTP 本篇不再赘述。如不太熟悉或有需要了解地方,可参考:
RESTful
一种 Web 软件的设计风格,采用统一的的接口和标准的 HTTP 方法,实现不同系统间的交互
- 基于 HTTP/1.1 协议:简单而轻量
- 统一资源标识符(URI):网络上的任何东西,如文本、图片、音视频等等,每一个资源对应一个 URI。客户通过 HTTP 方法对 URI 进行操作来实现资源的访问
- 统一接口:如GET、POST、PUT、DELETE等,此外还可以使用其他标准的协议:XML、JSON、HTML 等
- 统一状态码:如
OK = 200
,NOT FOUND = 404
等 - 无状态:服务端不保存客户端的请求状态,每个请求都需要提供相关信息(如 token)
- 可缓存:可以将资源保存在缓存中,重复的请求直接返回缓存中的数据
RESTful 基于 HTTP,因此受到 HTTP 协议的约束
RPC 协议
RPC 全名 Remote Procedure Call,即远程过程调用,是一种计算机通信协议,通常用于服务端之间的通信
-
RPC 的实现方式可以基于:HTTP、TCP、UDP、WS等协议
-
基于 HTTP 实现的 RPC 协议,同样是 客户端-服务端 模型。区别在于客户端也是一个服务
Feign
在 Java 的微服务体系中,通常使用 Feign 作为服务直间的远程通信
这是一种使用 HTTP/1.1 协议,实现的 RESTful 风格的轻量 API
- 突出特点是简洁易上手,像调用普通接口一样,调用其他服务的 API
- 因为使用 HTTP/1.1,进行报文传输时序列化方式还是我们常见的 JSON、From、XML 等
- 由于 HTTP 本质是明文传输,直接解析报文后数据是可读的,因此需要更多的方式进行安全提升
GRPC
在解释 gRPC 之前,需要先了解 gRPC 数据传输的序列化方式:Protocol Buffers——简称 protobuf
Protobuf
是一种语言无关、平台无关、可扩展的数据序列化格式,由 Google 开发
- 通过
.proto
文件 定义/添加 字段和消息类型,不需要修改现有代码(搭配代码生成使用) - 数据体积小,编解码快
- 二进制格式,安全可靠
- 支持注释、默认值,易于开发
protobuf 怎么做到体积小、解码快、更安全、可扩展?
先看一段 protobuf 约束代码
|
|
更多约束写法参考 官方文档 ,内容不多
现在我们有这样一个请求参数
|
|
如果是 Feign + HTTP/1.1,那么 name
和 age
也会被序列化传输
如果是 gRPC + HTTP/2,那么会做以下几件事:
- 拆解:去掉 key
name
和age
,根据约束定义的顺序序列化 - 传输:序列化成二进制,然后进行 流传输
- 取值:用 HTTP/2 的 头压缩 和 二进制帧 特性,反序列化需要根据压缩头的索引,从二进制流获取数据反序列化
- 组装:最后根据月约束文件,组装成定义的数据
HTTP 是明文传输,出于安全性考虑:
- 因此在传输前后一般还有证书校验、鉴权、加密、解密等过程
对于分布式微服务系统
- 还有网关、负载均衡等过程
GRPC 的特点
gRPC 是 Google 开发并开源的 高性能、开源、通用的 RPC 框架。有如下特点:
- 高性能:基于 HTTP/2,利用其多路复用、头部压缩、二进制帧等特性,提高传输效率
- 跨技术栈:跨语言。通过
.proto
文件自动生成对应语言的代码,只需要实现接口逻辑 - 流式处理:处理实时场景、持续性传输、数据交互等
- 双向认证:可以通过 SSL/TLS 加密传输,保证安全性
- 插件机制:提供请求拦截、Token 认证、日志、错误处理等扩展
gRPC 四种服务类型
- 简单 RPC:客户端请求,服务端响应
- 服务端流式 RPC:客户端一个请求,服务端持续传输(直播、下载)
- 客户端流式 RPC:客户端持续发送请求,服务端一个响应(文件上传)
- 双向流式 RPC:客户端和服务端持续发送消息(聊天、交互)