Golang架构直通车——理解gRPC

文章目录

  • gRPC概述
  • 关键技术——HTTP/2
    • 二进制分帧层
    • 数据流优先级
    • 流控制
    • 服务器推送
    • 标头压缩
  • gRPC Stream
  • gRPC Gateway

gRPC概述

gRPC具有以下特点:

  • 基于HTTP/2和Protobuf3的通用rpc框架, 继而提供了连接多路复用、Body 和 Header 压缩等机制。可以节省带宽、降低TCP链接次数、节省CPU使用和延长电池寿命等。
  • 支持服务端-服务端,客户端-服务端通信,由于使用了http2所以并不局限于服务器集群之间的通信。
  • IDL层使用了使用Protobuf3,多语言支持,非常适合团队的接口设计。

主要缺陷:

  • GRPC尚未提供连接池,需要自行实现
  • 尚未提供“服务发现”、“负载均衡”机制

关键技术——HTTP/2

HTTP/2 的主要目标是通过支持完整的请求与响应复用来减少延迟,通过有效压缩 HTTP 标头字段将协议开销降至最低,同时增加对请求优先级和服务器推送的支持。 为达成这些目标,HTTP/2 还给我们带来了大量其他协议层面的辅助实现,例如新的流控制、错误处理和升级机制。

HTTP/2 没有改动 HTTP 的应用语义。 HTTP 方法、状态代码、URI 和标头字段等核心概念一如往常。 不过,HTTP/2 修改了数据格式化(分帧)以及在客户端与服务器间传输的方式。

Golang架构直通车——理解gRPC_第1张图片

  • 双向数据流
    建立链接后,客户端和服务端均可主动发起请求(客户端和服务端序列号是以奇数和偶数开始自增的)。
  • 多路复用和流控
    采用多路复用的方式,在一条链接上可以跑多个请求,可以通过流控的方式按请求权重做控制。而HTTP/1.x 客户端需要使用多个连接才能实现并发和缩短延迟。
  • 头部压缩
    由于http1每个请求都会带有一大堆header,比如cookie啊之类的,这是http1的痛点(HTTP/1.x 不会压缩请求和响应标头,从而导致不必要的网络流量)。这会导致一些请求虽然用不到这个cookie,但是仍然会在请求时携带这些cookie,导致一个请求会多发很多个字节。
    头部压缩后,重复的header只需要发一次,相当于有动态表和静态表的概念:简单来说就是把一些重复的header固定下来,而之后的请求只需要发送diff的header,或者说与之前header不同的部分。
  • 内置安全(SSL/TSL支持)

二进制分帧层

HTTP/2 所有性能增强的核心在于新的二进制分帧层,它定义了如何封装 HTTP 消息并在客户端与服务器之间传输。HTTP/1.x 协议以换行符作为纯文本的分隔符,而 HTTP/2 将所有传输的信息分割为更小的消息和帧,并采用二进制格式对它们编码

新的二进制分帧机制改变了客户端与服务器之间交换数据的方式。 为了说明这个过程,我们需要了解 HTTP/2 的三个概念:

  • 数据流:已建立的连接内的双向字节流,可以承载一条或多条消息
  • 消息:与逻辑请求或响应消息对应的完整的一系列帧
  • 帧:HTTP/2 通信的最小单位,每个帧都包含帧头,至少也会标识出当前帧所属的数据流

简单来说,所有通信都在一个 TCP 连接上完成(复用,当然如果由于解码、编码都在一个CPU上完成,为了追求效率也可以用多个连接),此连接可以承载任意数量的双向数据流。每个数据流都有一个唯一的标识符和可选的优先级信息,用于承载双向消息。每条消息都是一条逻辑 HTTP 消息(例如请求或响应),包含一个或多个帧。来自不同数据流的帧可以交错发送,然后再根据每个帧头的数据流标识符重新组装。

Golang架构直通车——理解gRPC_第2张图片

在 HTTP/1.x 中,如果客户端要想发起多个并行请求以提升性能,则必须使用多个 TCP 连接,HTTP/2 中新的二进制分帧层突破了这些限制,实现了完整的请求和响应复用:客户端和服务器可以将 HTTP 消息分解为互不依赖的帧,然后交错发送,最后再在另一端把它们重新组装起来。

数据流优先级

将 HTTP 消息分解为很多独立的帧之后,我们就可以复用多个数据流中的帧,客户端和服务器交错发送和传输这些帧的顺序就成为关键的性能决定因素。 为了做到这一点,HTTP/2 标准允许每个数据流都有一个关联的权重和依赖关系

  • 可以向每个数据流分配一个介于 1 至 256 之间的整数。
  • 每个数据流与其他数据流之间可以存在显式依赖关系

数据流依赖关系和权重的组合让客户端可以构建和传递“优先级树”,表明它倾向于如何接收响应。
Golang架构直通车——理解gRPC_第3张图片

如上面的示例所示,数据流依赖关系和权重的组合明确表达了资源优先级,这是一种用于提升浏览性能的关键功能,网络中拥有多种资源类型,它们的依赖关系和权重各不相同。

注意:这里的资源优先级并不能保证特定的传输顺序,它保证的是分配的处理资源权重。

流控制

流控制是一种阻止发送方向接收方发送大量数据的机制,以免超出后者的需求或处理能力。

例如,客户端可能请求了一个具有较高优先级的大型视频流,但是用户已经暂停视频,客户端现在希望暂停或限制从服务器的传输,以免提取和缓冲不必要的数据。 再比如,一个代理服务器可能具有较快的下游连接和较慢的上游连接,并且也希望调节下游连接传输数据的速度以匹配上游连接的速度来控制其资源利用率;等等。

HTTP/2 未指定任何特定算法来实现流控制。 不过,它提供了简单的构建块并推迟了客户端和服务器实现,可以实现自定义策略来调节资源使用和分配,以及实现新传输能力,同时提升网页应用的实际性能和感知性能。

服务器推送

HTTP/2 新增的另一个强大的新功能是,服务器可以对一个客户端请求发送多个响应。 换句话说,除了对最初请求的响应外,服务器还可以向客户端推送额外资源,而无需客户端明确地请求。

HTTP/2 打破了严格的请求-响应语义,支持一对多和服务器发起的推送工作流,在浏览器内外开启了全新的互动可能性。为什么在浏览器中需要一种此类机制呢?一个典型的网络应用包含多种资源,客户端需要检查服务器提供的文档才能逐个找到它们。 那为什么不让服务器提前推送这些资源,从而减少额外的延迟时间呢? 服务器已经知道客户端下一步要请求什么资源,这时候服务器推送即可派上用场。

事实上,如果您在网页中内联过 CSS、JavaScript,或者通过数据 URI 内联过其他资产,那么您就已经亲身体验过服务器推送了。

标头压缩

在 HTTP/1.x 中,此元数据始终以纯文本形式,通常会给每个传输增加 500–800 字节的开销。如果使用 HTTP Cookie,增加的开销有时会达到上千字节。
而利用霍夫曼编码,可以在传输时对各个值进行压缩,而利用之前传输值的索引列表,我们可以通过传输索引值的方式对重复值进行编码,索引值可用于有效查询和重构完整的标头键值对。
Golang架构直通车——理解gRPC_第4张图片

作为一种进一步优化方式,会包含一个静态表和一个动态表:静态表提供了一个包含所有连接都可能使用的常用 HTTP 标头字段的列表;动态表最初为空,将根据在特定连接内交换的值进行更新。 因此,为之前未见过的值采用静态 Huffman 编码,并替换每一侧静态表或动态表中已存在值的索引,可以减小每个请求的大小。

gRPC Stream

Golang架构直通车——理解gRPC_第5张图片

  • 简单 RPC ( Simple RPC )
    这就是一般的rpc调用,一个请求对象对应一个返回对象。
  • 服务端流式 RPC ( Server-side streaming RPC )
    一个请求对象,服务端可以传回多个结果对象
  • 客户端流式RPC ( Client-side streaming RPC )
    客户端传入多个请求对象,服务端返回一个响应结果
  • 双向流式RPC ( Bidirectional streaming RPC )
    结合客户端流式rpc和服务端流式rpc,可以传入多个对象,返回多个响应对象

gRPC Gateway

使用grpc也会面临一个问题,我们的微服务对外一定是要提供Restful接口的(我们通常把RPC用作内部通信,而使用Restful Api进行外部通信)。为了避免写两套应用,我们使用grpc-gateway把gRPC转成HTTP。服务接收到HTTP请求后,grpc-gateway把它转成gRPC进行处理,然后以JSON形式返回数据。
简单来说Gateway相当于是gRPC和http之间的代理

你可能感兴趣的:(Golang架构直通车)