gRPC
gRPC-入门
grpc 介绍
gRPC 是一个高性能、开源和通用的 RPC 框架,面向移动和 HTTP/2 设计。目前提供 C、Java 和 Go 语言版本,分别是:grpc, grpc-java, grpc-go. 其中 C 版本支持 C, C++, Node.js, Python, Ruby, Objective-C, PHP 和 C# 支持.
gRPC 基于 HTTP/2 标准设计,带来诸如双向流、流控、头部压缩、单 TCP 连接上的多复用请求等特。这些特性使得其在移动设备上表现更好,更省电和节省空间占用。
grpc 微服务和 Grpc 如何演化
json pb
web ----> gateway ----> service
grpc 跨平台应用(跨语言演示)
环境安装
先安装 Protobuf 编译器 protoc,下载地址:https://github.com/google/protobuf/releases
我的是 windows,将压缩包 bin 目录下的 exe 放到环境 PATH 目录中即可。
然后获取插件支持库
// gRPC运行时接口编解码支持库
go get -u github.com/golang/protobuf/proto
// 从 Proto文件(gRPC接口描述文件) 生成 go文件 的编译器插件
go get -u github.com/golang/protobuf/protoc-gen-go
最后获取 go 的 gRPC 包
go get google.golang.org/grpc
gRPC-流式处理
1.1 什么是流式处理
gRPC 能支持流式调用本质是因为 gRPC 通信是基于 HTTP/2 实现的,HTTP/2 具有流的概念,流是为了实现 HTTP/2 的多路复用。流是服务器和客户端在 HTTP/2 连接内用于交换帧数据的独立双向序列,逻辑上可看做一个较为完整的交互处理单元,即表达一次完整的资源请求、响应数据交换流程
1.2 流式处理 api 介绍
服务端流式 RPC
即客户端发送一个请求给服务端,可获取一个数据流用来读取一系列消息。客户端从返回的数据流里一直读取直到没有更多消息为止。
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse){
}
客户端流式 RPC
即客户端用提供的一个数据流写入并发送一系列消息给服务端。一旦客户端完成消息写入,就等待服务端读取这些消息并返回应答。
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse) {
}
双向流式 RPC
即两边都可以分别通过一个读写数据流来发送一系列消息。这两个数据流操作是相互独立的,所以客户端和服务端能按其希望的任意顺序读写,例如:服务端可以在写应答前等待所有的客户端消息,或者它可以先读一个消息再写一个消息,或者是读写相结合的其他方式。每个数据流里消息的顺序会被保持。
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse){
}
1.3 流式处理应用场景
文件流,视频流或者实时通信
1.4 流式处理实现原理
HTTP2 协议分析
HTTP/2 并不是对 HTTP 协议的重写,相对于 HTTP/1,HTTP/2 的侧重点主要在性能。请求方法,状态码和语义和 HTTP/1 都是相同的,可以使用与 HTTP/1.x 相同的 API(可能有一些小的添加)来表示协议。
HTTP/2主要有两个规范组成
- Hypertext Transfer Protocol version 2 (超文本传输协议版本 2)
- HPACK - HTTP/2的头压缩 (HPACK 是一种头部压缩算法)
HTTP2 中的一些概念
帧:数据通信的最小信息单位
流:存在与 TCP 连接中的一个虚拟通道(双向的,能往过流,也能往回流)
HTTP2 的特性
HTTP/2 支持 HTTP/1.1 的所有核心功能,但旨在通过多种方式提高效率
HTTP/2 采用二进制传输数据,而非 HTTP/1 的文本格式传输
HTTP/2 基本协议单元是帧,比如 head(头部信息)帧,data(传输数据细信息)帧
HTTP/2 使用流技术支持多路复用,也就是说提供了在单个连接上复用 HTTP 请求和响应的能力, 多个请求或响应可以同时在一个连接上使用流.
HTTP/2 支持压缩头部帧,允许将多个请求压缩成成一个分组,而且在客户端和服务器端分别头部信息建立索引,相同的表头只需要传输索引就可以。
HTTP/2 支持对请求划分优先级(就是流的优先级)
HTTP/2 支持 Server Push 技术
在 HTTP/1 中是按照顺序,一起请求,一次响应,而 HTTP/2 协议可以做到在一个 TCP 连接中并行执行,而不用按照顺序一对一。
HTTP2 的原理
多路复用
HTTP/2 将每一个请求变成流,每一个流都有自己的 ID,有自己的优先级,这些流可以由客户端发送到服务端,也可以由服务端发送到客户端,将数据划分为帧,头部信息为 head 帧,实体信息为 data 帧,最后将这些流乱序发送到一个 TCP 连接中,
HTTP/2 中,在一个浏览器同域名下的所有请求都是在单个连接中完成,这个连接可以承载任意数量的双向数据流,每个数据流都以消息的形式发送,而消息又由一个或多个帧组成,多个帧之间可以乱序发送,根据帧首部的流标识可以将多个帧重新组装成一个流。
在 HTTP/1 中,如果想并发发送多个请求,必须创建多个 TCP 连接,而且浏览器为了减少负载,会对同一域名下的 TCP 连接做限制,这样当请求量比较大时,会引起阻塞,
服务器推送
HTTP /1 中客户端往服务端发送请求严格遵守一个请求,一个响应,比如客户端请求展示网页时,服务端发挥 HTML 内容,浏览器解析时发送 css,js 请求,服务端又返回 css,js 文件,那么服务端为什么不能在返回网页时就推送 css,js 内容给客户端呢,在 HTTP/2中这已功能已经支持,
服务端主动推送也会遵守同源策略,不会随便推送第三方的资源到客户端
如果服务端推送资源是呗客户端缓存过的,客户端是有权力拒绝服务端的推送的,浏览器可以通过发送 RST_STREAM 帧来拒收。
每一个服务端推送的资源都是一个流
头部压缩
HTTP /1 的请求头较大,而且是以纯文本发送,HTTP/2 对消息头进行了压缩,采用的是 HACK 算法,能够节省消息头占用的网络流量,其主要是在两端建立了索引表,消息头在传输时可以采用索引,而 HTTP/1.x 每次请求,都会携带大量冗余头信息,浪费了很多带宽资源。
帧的描述
所有帧都以固定的 9 字节头开头,后跟可变长度的有效载荷,组成如下:
长度:帧有效负载的长度表示为无符号的 24 位整数
类型:8 位类型的帧,帧类型确定帧的格式和语义
标志:为特定于帧类型的布尔标志保留的 8 位字段
R:保留的 1 位字段。该位的语义未定义
流标识符:流标识符,表示为无符号 31 位整数,客户端发起流标识符必须时奇数,服务端发起的流标识符必须是偶数
9 字节总共是:9 * 8 = 72 位
上面的描述 24 + 8 + 8 +1 + 31 = 72 位
gRPC 和 HTTP2 的关系
gRPC 设计时的初衷:gRPC 的设计目标是在任何环境下运行,支持可插拔的负载均衡,跟踪,运行状况检查和身份验证。它不仅支持数据中心内部和跨数据中心的服务调用,它也适用于分布式计算的最后一公里,将设备,移动应用程序和浏览器连接到后端服务,同时,它也是高性能的,而 HTTP/2恰好支持这些。
HTTP/2天然的通用性满足各种设备,场景
HTTP/2的性能相对来说也是很好的,除非你需要极致的性能
HTTP/2的安全性非常好,天然支持 SSL
HTTP/2的鉴权也非常成熟
gRPC 基于 HTTP/2多语言实现也更容易
grpc-安全
1.1 什么是 grpc 安全
GRPC是基于HTTP/2协议的, 因此其安全性也是通过HTTP2协议来保证。
HTTP/2默认并没有加密, 但是它定义了TLS的轮廓, 因此与HTTPS类似都是利用 TLS来保证安全性
SSL/TLS协议的基本思路是采用公钥加密法,客户端向服务器端索要公钥,然后用公钥加密信息,服务器收到密文后,用自己的私钥解密。
1.2 grpc 身份验证和授权
支持的授权机制
SSL/TLS
gRP 集成 SSL/TLS 并对服务端授权所使用的 SSL/TLS 进行了改良,对客户端和服务端交换的所有数据进行了加密。对客户端来讲提供了可选的机制提供凭证来获得共同的授权。
OAuth 2.0
gRPC 提供通用的机制(后续进行描述)来对请求和应答附加基于元数据的凭证。当通过 gRPC 访问 Google API 时,会为一定的授权流程提供额外的获取访问令牌的支持,这将通过以下代码例子进行展示。
警告:Google OAuth2 凭证应该仅用于连接 Google 的服务。把 Google 对应的 OAuth2 令牌发往非 Google 的服务会导致令牌被窃取用作冒充客户端来访问 Google 的服务。
API
为了减少复杂性和将混乱最小化, gRPC 以一个统一的凭证对象来进行工作。
凭证可以是以下两类:
频道凭证, 被附加在 频道上, 比如 SSL 凭证。
调用凭证, 被附加在调用上(或者 C++ 里的 客户端上下文)。 凭证可以用组合频道凭证来进行组合。一个组合频道凭证可以将一个频道凭证和一个调用凭证关联创建一个新的频道凭证。结果在这个频道上的每次调用会发送组合的调用凭证来作为授权数据。 例如,一各频道凭证可以由一个Ssl 凭证和一个访问令牌凭证生成。结果是在这个频道上的每次调用都会发送对应的访问令牌。 调用凭证可以用 组合凭证来组装。组装后的 调用凭证应用到一个客户端上下文里,将触发发送这两个调用凭证的授权数据。
1.3 grpc 日志记录和诊断
grpc 定义了grpclog包,并定义了LoggerV2的接口,因此,只要通过zap实现LoggerV2的接口,并通过SetLoggerV2(l LoggerV2)接口将实现的对象设置到grpclog包中,那么grpc将使用zap进行日志输出,同时上层应用也可以使用grpclog进行业务日志打印
grpc-集群与部署
1.1 什么是 grpc 集群
集群(cluster)就是一组计算机,它们作为一个整体向用户提供一组网络资源,这些单个的计算机系统就是集群的节点(node)。集群提供了以下关键的特性。
(一) 可扩展性。集群的性能不限于单一的服务实体,新的服务实体可以动态的加入到集群,从而增强集群的性能。
(二) 高可用性。集群通过服务实体冗余使客户端免于轻易遭遇到“out of service”警告。当一台节点服务器发生故障的时候,这台服务器上所运行的应用程序将在另一节点服务器上被自动接管。消除单点故障对于增强数据可用性、可达性和可靠性是非常重要的。
(三) 负载均衡。负载均衡能把任务比较均匀的分布到集群环境下的计算和网络资源,以便提高数据吞吐量。
(四) 错误恢复。如果集群中的某一台服务器由于故障或者维护需要而无法使用,资源和应用程序将转移到可用的集群节点上。这种由于某个节点中的资源不能工作,另一个可用节点中的资源能够透明的接管并继续完成任务的过程叫做错误恢复。
部署一系列的 grpc 服务器提供服务。
1.2 grpc 如何实现集群负载均衡
负载均衡处理方案有三种:
- 负载均衡软件 HAProxy, LVS 等
- 客户端进程内负载均衡
- 客户端机器部署独立负载均衡进程 类似QConf-agent
gRPC负载平衡的主要实现机制是外部负载平衡,即通过外部负载平衡器来向客户端提供更新后的服务器列表。
gRPC客户端也内置对少量几种负载平衡策略API的支持,其中包括grpclb策略(该策略实现了外部负载平衡),但并不鼓励用户在gRPC中添加更多的策略。新的负载平衡策略应该在外部负载平衡器中实现。
1.3 grpc 如何部署
使用 docker 和 k8s 部署 grpc 服务