关于grpc和http2的关系的信息

http://www.itjxue.com  2023-01-27 22:43  来源:未知  点击次数: 

grpc进阶-HTTP/2

title: grpc进阶-HTTP/2

date: 2020-08-22 14:39:55

面试的时候,面试官问我 gRPC 所使用的 HTTP/2 协议有何优势,我支支吾吾没答好。

面试结束后,深刻意识到自身的问题:学习新技术框架,常常不求甚解,缺乏刨根问底的精神。

因此,抽空好好学习一下 HTTP/2 。

也借此勉励各位,千万不能只会 Hello world 。

众所周知,HTTP/1.0 存在如下问题:

当同时有多个HTTP请求时,会造成TCP连接频繁地创建和销毁(三次握手、四次挥手),十分影响性能。

为了解决这个问题,HTTP/1.1 提出了长连接 Keep-Alive :多个HTTP请求可复用一个TCP连接,当没有HTTP请求时,TCP连接还会保持一段时间才关闭。

但随着网站的请求越来越多,对网络通信性能要求越来越高,HTTP/1.1 也逐渐暴露出了一些问题:

为了解决这一系列问题,HTTP/2 出现了。

2009年,谷歌公布了一个实验性协议—— SPDY ,用于解决 HTTP/1.1 的性能问题。

2012年,察觉到 SPDY 协议的趋势,HTTP工作组开始征集 HTTP/2 的建议,并基于 SPDY 制定了第一个 HTTP/2 草案。

2015年,IESG 批准 HTTP/2 和 HPACK 草案,RFC 7540 (HTTP/2) 和 RFC 7541 (HPACK) 发布。

官方文档: RFC 7540

官方介绍:

其中,提到了三个重点:

以下,将从这三点依次介绍。

在 HTTP/1.1 中,头部数据以文本形式传输(ASCII编码:一个字符占用一个字节)。

而在 HTTP/2 中,则采用 HPACK 算法 进行压缩。

HPACK 算法原理大致如下(参考博客: HTTP2 详解 ):

二进制分帧层是 HTTP/2 性能增强的核心 ,存在于应用层 HTTP/2 与传输层 TCP 之间。

它将一个 HTTP/2 请求报文( 流 )划分成更小的 帧(frame) ,再将多个请求的帧合并成一个新的报文交给TCP。

接收方TCP将报文交给二进制分帧层后,它会将每一帧抽离出来,拼接到对应的 HTTP/2 报文中。

多个 HTTP/2 请求复用一个 TCP 报文,从而实现了并发。相比于 HTTP/1.1 中一个请求独占一个 TCP 报文,这就像数据交换中 报文交换到分组交换的改进 。

同时,这也与 进程并发 的思想相同。

帧的结构如下:

主要字段的含义如下:

更详细的字段解析,可查看博客和官方文档。

这也就是上文所提到的:发送方将 HTTP/2 报文(流)分解成不同的帧,并将属于不同 HTTP/2 报文(流)的帧合并在一个 TCP 报文中,然后发送,最后接收方再把它们重新组装起来。

正是由于 HTTP/2 的多路复用, 对于同一个域名,浏览器只需创建一个 TCP 连接 。

由于可以同时发送多个 HTTP/2 报文的帧,那么,优先发送哪些报文的帧,就成了一个问题。

在 HTTP/2 中,每个 HTTP/2 报文(流)都可以被分配优先级,优先级高的先发送。

由于接收方需要缓存每个报文已接受的帧(所有帧到达后,再拼接起来),所以,为了防止发送方发送过快过多,导致接收方缓存溢出,HTTP/2 提供了流量控制。

这与 TCP 流量控制 大同小异。

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

这是不是类似于 Websocket ?

测试网站:

GRPC的理解

grpc每个流只有一个grpc的数据帧,这个数据帧在传输的时候,会拆成多个http2的数据帧进行传输,然后在接受端,把所有http2的数据帧拼接成grpc的数据帧,再反序列化成请求的结构体。如果一次传输数据过大,在序列化和反序列化的时候,都会占用大量的cpu,不仅仅序列化,单纯的内存复制,也会占用大量cpu,而且,传输的时候,对带宽的影响也是很大的。因此,grpc不推荐一次传输大量数据,如果有大量数据要传输,则使用stream模式。【当然,grpc单次数据传输的大小限制是可以修改的,但是不建议你这么做】【默认最大消息大小为4MB

【不断修改增加服务端和客户端消息大小,每次请求不一定需要全部数据,会导致性能上和资源上的浪费】

【grpc协议层是基于http2设计的(但之前看一片测评文章,结构发现文件传输的时候速度有点慢,因为大量数据传输的场景瓶颈在于tcp,如果还在一个tcp上进行多路复用,那只会加剧锁竞争)】

【4 MB 的限制是为了保护没有考虑过消息大小限制的客户端/服务器。 gRPC 本身可以提高很多(100 MB),但大多数应用程序可能会受到轻微攻击或意外内存不足,从而允许该大小的消息。】

【grpc本质是为了提高单连接的利用率,如果单个stream上传输大量的数据,那么其他stream的数据就很难得到及时的传输,grpc适用于大量的请求,但是每次请求的传输数据量不大的情况】

【如果单次传输的数据量过大,建议从新开一个tcp连接,也就是用http1.1,因为在数据量很大的情况下,瓶颈在于底层的tcp】

【同理,在IM系统中,拉消息也建议使用http1.1的接口,避免占用大量的长连带宽,影响下行推送及时性】

【http1.1有维护连接池,每次请求都会独占一个tcp连接,所以,在传输大量数据的场景下,也不会影响到其他请求的数据传输,瓶颈在于机器性能】

grpc 连接池

grpc-源码-网络模型

golang 的grpc库是

grpc server端和服务端网络协议是在tcp基础上的 http2协议,http2协议负责grpc基础的数据传输、连接管理、流控等, 具体的业务层service 定义是基于 protobuf的

整个的网络过程和关键点如下图

说明:

TCP KeepAlive则是为了探测/保鲜(心跳检测,连接错误检测):用于探测对端的状态及网络情况(有可能客户端崩溃、强制关闭了应用、主机不可达等等),也有保鲜功能。比如如防止nat超时。TCP keepalive则是通过发送发送侦测包实现。在Linux中通过net.ipv4.tcp_keepalive_intvl,net.ipv4.tcp_keepalive_probes,net.ipv4.tcp_keepalive_time配置。比如gnet 网络框架中的实现

(责任编辑:IT教学网)

更多

推荐软件水平考试文章