gRPC 的原理 介绍带你从头了解gRPC
gRPC 的原理
什么是gRPC
gRPC的官方介绍是:gRPC是一个现代的、高性能、开源的和语言无关的通用 RPC 框架,基于 HTTP2 协议设计,序列化使用PB(Protocol Buffer),PB 是一种语言无关的高性能序列化框架,基于 HTTP2+PB 保证了的高性能。
好吧我知道对于一个初学者来说这并没有意义,首先我们需要提炼关键,来回答以下几个问题,从而真正明白gRPC到底是什么?
- gRPC 和 RPC 的区别
- HTTP2 协议是什么?基于他的设计是什么意思?
- 序列化PB(Protocol Buffer) 是什么?
gRPC 和RPC 的区别
RPC(Remote Procedure Call)是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。
gRPC是Google开发的一个RPC系统,它使用HTTP/2协议进行通信,并使用Protocol Buffers作为接口描述语言。
这使得gRPC比传统的RPC更加强大,可以支持流式请求和响应,以及其他复杂的交互模式。
总结:RPC 是一个框架,已经写好一些功能,但是并不适合谷歌的应用场景,在这个基础上 谷歌 对RPC 框架进行了迭代开发,形成了gRPC。
HTTP2 协议是什么?基于他的设计是什么意思?
HTTP/2是HTTP协议的第二个主要版本,它在性能优化、服务器推送、头信息压缩、协议复用等方面都有显著的改进。
基于HTTP/2的设计意味着gRPC在设计时充分利用了HTTP/2的这些特性,
例如,它可以在一个TCP连接上并行发送多个请求和响应,减少了网络延迟。
总结:http2 是一个通讯规定,基于http2 的协议设计是指在使用这个通讯规定上进行的程序软件设计。
gRPC 即是基于RPC协议又基于HTTP2协议,这两种协议怎么融合的?
在明确上述两种协议的具体内容之后,我们就可以回答这个问题了。在gRPC中RPC是它的业务逻辑基本框架,HTTP2 是它的通讯逻辑基本原理。
从而我们可以理解这张图:
![[Pasted image 20231114145840.png]]
二进制序列化PB(Protocol Buffer) 是什么?
Protocol Buffers(简称PB)是Google开发的一种数据序列化协议(类似于XML、JSON、hessian)。
它能够将数据结构以高效和可扩展的格式进行序列化,可以用于网络通信和数据存储等场景。
上面的解释很绕,让我们先明确什么是序列化:简单点说:就是把信息按照固定格式组织起来,为的是解决不同系统、不同编程语言、不同平台之间的传输存储问题。
序列化是指将对象转换为可以在网络传输或存储中使用的格式,以便在需要时可以重新构造出原始对象。在序列化过程中,对象的状态被转换为字节流或其他可传输的形式,以便可以在不同的系统、编程语言或平台之间进行传输或存储。
序列化的主要目的是实现对象的持久化、跨网络传输和跨平台通信。通过序列化,可以将对象转换为字节流,然后可以将字节流保存到文件中、通过网络发送给其他系统,或者在不同的程序之间进行交互。在接收方,可以通过反序列化将字节流转换回原始对象,以便进行进一步的处理或使用。
常见的序列化格式包括JSON、XML和Protocol Buffers(Protobuf)等。不同的序列化格式具有不同的特点和适用场景,选择合适的序列化格式取决于具体的需求和使用环境。
怎么用呢?这里我们以PB为例:
Protocol Buffers(简称Protobuf)使用特定的语法和编译器来定义消息的结构和字段,然后通过编译器生成相应的代码,用于序列化和反序列化对象。
下面是使用C++代码的示例,展示了如何使用Protobuf进行对象的序列化和反序列化:
-
定义消息结构
首先,需要使用Protobuf的语法定义消息的结构和字段。例如,创建一个名为Person
的消息类型,包含name
和age
字段:syntax = "proto3";message Person {string name = 1;int32 age = 2; }
-
生成代码
使用Protobuf的编译器将上述定义的消息结构编译为相应的代码。在C++中,可以使用protoc
命令行工具进行编译:protoc --cpp_out=. person.proto
这将生成
person.pb.h
和person.pb.cc
两个文件,包含了用于序列化和反序列化Person
消息的代码。 -
序列化对象
在C++代码中,可以使用生成的代码来创建Person
对象,并将其序列化为字节流:#include "person.pb.h"// 创建Person对象 Person person; person.set_name("John"); person.set_age(25);// 序列化为字节流 std::string serialized_data; person.SerializeToString(&serialized_data);
SerializeToString
方法将Person
对象序列化为一个字符串。 -
反序列化对象
反之,可以将序列化的字节流反序列化为原始的Person
对象:// 反序列化为Person对象 Person deserialized_person; deserialized_person.ParseFromString(serialized_data);// 访问反序列化后的字段 std::string name = deserialized_person.name(); int age = deserialized_person.age();
ParseFromString
方法将字节流解析为Person
对象,并可以通过访问相应的字段获取数据。
需要注意的是,上述示例中的代码是使用C++语言进行的,如果使用其他编程语言,操作步骤会有所不同,但基本原理是相似的。
gRPC的工作方式
在通过上述 的详细介绍之后,我们就可以介绍gRPC 的工作方式来说明什么是gRPC 了。
![[Pasted image 20231114151128.png]]
上图中使用的是c++和红宝石以及安卓开发三种语言、平台、系统都不同的实例间通讯,展示的是gRPC 的 通用性
![[Pasted image 20231114151324.png]]
上图是解释了信息在gRPC 中是怎样流转的。展示的是gRPC 的 序列化
为什么使用gRPC
gRPC 的原理
- 自由,开放:让所有人,所有平台都能使用,其实就是开源,跨平台,跨语言
- 协议可插拔:不同的服务可能需要使用不同的消息通信类型和编码机制,例如,JSON、XML和Thirft,所以协议应允许可插拔机制,还有负载均衡,服务发现,日志,监控等都支持可插拔机制
- 阻塞和非阻塞:支持客户端和服务器交换的消息序列的异步和同步处理。这对于在某些平台上扩展和处理至关重要
- 取消和超时:一次RPC操作可能是持久并且昂贵的,应该允许客户端设置取消RPC通信和对这次通信加上一个超时时间
- 拒绝:必须允许服务器通过在继续处理请求的同时拒绝新请求的到来并优雅地关闭。
- 流处理:存储系统依靠流和流控制来表达大型数据集,其他服务,如语音到文本或股票行情,依赖于流来表示与时间相关的消息序列
- 流控制:计算能力和网络容量在客户端和服务器之间通常是不平衡的。流控制允许更好的缓冲区管理,以及过度活跃的对等体提供对DOS的保护。
- 元数据交换:认证或跟踪等常见的跨领域问题依赖于不属于服务声明接口的数据交换。依赖于他们将这些特性演进到服务,暴露API来提供能力。
- 标准化状态码:客户端通常以有限的方式响应API调用返回的错误。应约束状态码名称空间,以使这些错误处理决策更加清晰。如果需要更丰富的特定领域的状态,则可以使用元数据交换机制来提供该状态。
- 互通性:报文协议(Wire Protocol)必须遵循普通互联网基础框架
gRPC 的一些特性
-
gRPC基于服务的思想:定义一个服务,描述这个服务的方法以及入参出参,服务器端有这个服务的具体实现,客户端保有一个存根,提供与服务端相同的服务。
-
gRPC默认采用protocol buffer作为IDL(Interface Description Lanage)接口描述语言,服务之间通信的数据序列化和反序列化也是基于protocol buffer的,因为protocol buffer的特殊性,所以gRPC框架是跨语言的通信框架(与编程语言无关性),也就是说用Java开发的基于gRPC的服务,可以用GoLang编程语言调用
-
gRPC同时支持同步调用和异步调用,同步RPC调用时会一直阻塞直到服务端处理完成返回结果,异步RPC是客户端调用服务端时不等待服务段处理完成返回,而是服务端处理完成后主动回调客户端告诉客户端处理完成
-
gRPC是基于http2协议实现的,http2协议提供了很多新的特性,并且在性能上也比http1提搞了许多,所以gRPC的性能是非常好的
-
gRPC并没有直接实现负载均衡和服务发现的功能,但是已经提供了自己的设计思路。已经为命名解析和负载均衡提供了接口
-
基于http2协议的特性:gRPC允许定义如下四类服务方法
- 一元RPC:客户端发送一次请求,等待服务端响应结构,会话结束,就像一次普通的函数调用这样简单
- 服务端流式RPC:客户端发起一起请求,服务端会返回一个流,客户端会从流中读取一系列消息,直到没有结果为止
- 客户端流式RPC:客户端提供一个数据流并写入消息发给服务端,一旦客户端发送完毕,就等待服务器读取这些消息并返回应答
- 双向流式RPC:客户端和服务端都一个数据流,都可以通过各自的流进行读写数据,这两个流是相互独立的,客户端和服务端都可以按其希望的任意顺序独写
gRPC的使用场景
-
低延迟,高度可扩展的分布式系统
-
开发与云服务器通信的客户端
-
设计一个准确,高效,且与语言无关的新协议时
-
分层设计,以实现扩展,例如。身份验证,负载平衡,日志记录和监控等
-
谷歌长期以来一直在gRPC中使用很多基础技术和概念。目前正在谷歌的几个云产品和谷歌面向外部的API中使用。Square,Netflix,CoreOS,Docker,CockroachDB,Cisco,Juniper Networks以及许多其他组织和个人也在使用它。
gRPC的数据封装和数据传输问题
这里我们主要介绍pb的工作方式,即怎样封装数据;
数据封装
gRPC 使用的是自己的封装方式 Protocol Buffer
简称ProtoBuf,是Google开发的一种跨语言、跨平台、可扩展的用于序列化数据协议。
下面是一个protoBuf 的样例
// XXXX.proto
// rpc服务的类 service关键字, Test服务类名
service Test {
// rpc 关键字,rpc的接口
rpc HowRpcDefine (Request) returns (Response) ; // 定义一个RPC方法
}
// message 类,c++ class
message Request {
//类型 | 字段名字| 标号
int64 user_id = 1;
string name = 2;
}
message Response {
repeated int64 ids = 1; // repeated 表示数组
Value info = 2; // 可嵌套对象
map<int, Value> values = 3; // 可输出map映射
}
message Value {
bool is_man = 1;
int age = 2;
}
以上是一个使用样例,包含方法定义、入参、出参。可以看出有几个明确的特点:
- 有明确的类型,支持的类型有多种
- 每个field会有名字
- 每个field有一个数字标号,一般按顺序排列(下文编解码会用到这个点)
- 能表达数组、map映射等类型
- 通过嵌套message可以表达复杂的对象
- 方法、参数的定义落到一个.proto 文件中,依赖双方需要同时持有这个文件,并依此进行编解码
protobuf作为一个以跨语言为目标的序列化方案,protobuf能做到多种语言以同一份proto文件作为约定,不用A语言写一份,B语言写一份,各个依赖的服务将proto文件原样拷贝一份即可。
但.proto文件并不是代码,不能执行,要想直接跨语言是不行的,必须得有对应语言的中间代码才行,中间代码要有以下能力:
- 将message转成对象,例如C++里是class,golang里是struct,需要各自表达后,才能被理解
- 需要有进行编解码的代码,能解码内容为自己语言的对象、能将对象编码为对应的数据
在完成数据封装之后,我们就准备好了将它传输出去,接下来就是数据传输了。
数据传输
grpc采用HTTP2.0,相对于HTTP1.0 在 更快的传输 和 更低的成本 两个目标上做了改进。有以下几个基本点:
- HTTP2 未改变HTTP的语义(如GET/POST等),只是在传输上做了优化
- 引入帧、流的概念,在TCP连接中,可以区分出多个request/response
- 一个域名只会有一个TCP连接,借助帧、流可以实现多路复用,降低资源消耗
- 引入二进制编码,降低header带来的空间占用
HTTP1.1核心问题在于:在同一个TCP连接中,没办法区分response是属于哪个请求,一旦多个请求返回的文本内容混在一起,则没法区分数据归属于哪个请求,所以请求只能一个个串行排队发送。这直接
导致了TCP资源的闲置。
HTTP2为了解决这个问题,提出了 流 的概念,每一次请求对应一个流,有一个唯一ID,用来区分不同的请求。基于流的概念,进一步提出了 帧 ,一个请求的数据会被分成多个帧,方便进行数据分割传输,每个帧都唯一属于某一个流ID,将帧按照流ID进行分组,即可分离出不同的请求。这样同一个TCP连接中就可以同时并发多个请求,不同请求的帧数据可穿插在一起,根据流ID分组即可。HTTP2.0基于这种二进制协议的乱序模式 (Duplexing),直接解决了HTTP1.1的核心痛点,通过这种复用TCP连接的方式,不用再同时建多个连接,提升了TCP的利用效率。
总结
传输使用 http2 协议,是在tcp链接完成之后,再在应用层发送时的一个协议,通过流 ID 和 帧报文的两个概念 解决了传输拥塞的问题。我们将这种方式称之为 tcp链接复用。
gRPC 的原理
什么是gRPC
gRPC的官方介绍是:gRPC是一个现代的、高性能、开源的和语言无关的通用 RPC 框架,基于 HTTP2 协议设计,序列化使用PB(Protocol Buffer),PB 是一种语言无关的高性能序列化框架,基于 HTTP2+PB 保证了的高性能。
好吧我知道对于一个初学者来说这并没有意义,首先我们需要提炼关键,来回答以下几个问题,从而真正明白gRPC到底是什么?
- gRPC 和 RPC 的区别
- HTTP2 协议是什么?基于他的设计是什么意思?
- 序列化PB(Protocol Buffer) 是什么?
gRPC 和RPC 的区别
RPC(Remote Procedure Call)是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。
gRPC是Google开发的一个RPC系统,它使用HTTP/2协议进行通信,并使用Protocol Buffers作为接口描述语言。
这使得gRPC比传统的RPC更加强大,可以支持流式请求和响应,以及其他复杂的交互模式。
总结:RPC 是一个框架,已经写好一些功能,但是并不适合谷歌的应用场景,在这个基础上 谷歌 对RPC 框架进行了迭代开发,形成了gRPC。
HTTP2 协议是什么?基于他的设计是什么意思?
HTTP/2是HTTP协议的第二个主要版本,它在性能优化、服务器推送、头信息压缩、协议复用等方面都有显著的改进。
基于HTTP/2的设计意味着gRPC在设计时充分利用了HTTP/2的这些特性,
例如,它可以在一个TCP连接上并行发送多个请求和响应,减少了网络延迟。
总结:http2 是一个通讯规定,基于http2 的协议设计是指在使用这个通讯规定上进行的程序软件设计。
gRPC 即是基于RPC协议又基于HTTP2协议,这两种协议怎么融合的?
在明确上述两种协议的具体内容之后,我们就可以回答这个问题了。在gRPC中RPC是它的业务逻辑基本框架,HTTP2 是它的通讯逻辑基本原理。
从而我们可以理解这张图:
![[Pasted image 20231114145840.png]]
二进制序列化PB(Protocol Buffer) 是什么?
Protocol Buffers(简称PB)是Google开发的一种数据序列化协议(类似于XML、JSON、hessian)。
它能够将数据结构以高效和可扩展的格式进行序列化,可以用于网络通信和数据存储等场景。
上面的解释很绕,让我们先明确什么是序列化:简单点说:就是把信息按照固定格式组织起来,为的是解决不同系统、不同编程语言、不同平台之间的传输存储问题。
序列化是指将对象转换为可以在网络传输或存储中使用的格式,以便在需要时可以重新构造出原始对象。在序列化过程中,对象的状态被转换为字节流或其他可传输的形式,以便可以在不同的系统、编程语言或平台之间进行传输或存储。
序列化的主要目的是实现对象的持久化、跨网络传输和跨平台通信。通过序列化,可以将对象转换为字节流,然后可以将字节流保存到文件中、通过网络发送给其他系统,或者在不同的程序之间进行交互。在接收方,可以通过反序列化将字节流转换回原始对象,以便进行进一步的处理或使用。
常见的序列化格式包括JSON、XML和Protocol Buffers(Protobuf)等。不同的序列化格式具有不同的特点和适用场景,选择合适的序列化格式取决于具体的需求和使用环境。
怎么用呢?这里我们以PB为例:
Protocol Buffers(简称Protobuf)使用特定的语法和编译器来定义消息的结构和字段,然后通过编译器生成相应的代码,用于序列化和反序列化对象。
下面是使用C++代码的示例,展示了如何使用Protobuf进行对象的序列化和反序列化:
-
定义消息结构
首先,需要使用Protobuf的语法定义消息的结构和字段。例如,创建一个名为Person
的消息类型,包含name
和age
字段:syntax = "proto3";message Person {string name = 1;int32 age = 2; }
-
生成代码
使用Protobuf的编译器将上述定义的消息结构编译为相应的代码。在C++中,可以使用protoc
命令行工具进行编译:protoc --cpp_out=. person.proto
这将生成
person.pb.h
和person.pb.cc
两个文件,包含了用于序列化和反序列化Person
消息的代码。 -
序列化对象
在C++代码中,可以使用生成的代码来创建Person
对象,并将其序列化为字节流:#include "person.pb.h"// 创建Person对象 Person person; person.set_name("John"); person.set_age(25);// 序列化为字节流 std::string serialized_data; person.SerializeToString(&serialized_data);
SerializeToString
方法将Person
对象序列化为一个字符串。 -
反序列化对象
反之,可以将序列化的字节流反序列化为原始的Person
对象:// 反序列化为Person对象 Person deserialized_person; deserialized_person.ParseFromString(serialized_data);// 访问反序列化后的字段 std::string name = deserialized_person.name(); int age = deserialized_person.age();
ParseFromString
方法将字节流解析为Person
对象,并可以通过访问相应的字段获取数据。
需要注意的是,上述示例中的代码是使用C++语言进行的,如果使用其他编程语言,操作步骤会有所不同,但基本原理是相似的。
gRPC的工作方式
在通过上述 的详细介绍之后,我们就可以介绍gRPC 的工作方式来说明什么是gRPC 了。
)
包浆老图
上图中使用的是c++和红宝石以及安卓开发三种语言、平台、系统都不同的实例间通讯,展示的是gRPC 的 通用性
上图是解释了信息在gRPC 中是怎样流转的。展示的是gRPC 的 序列化
为什么使用gRPC
gRPC 的原理
- 自由,开放:让所有人,所有平台都能使用,其实就是开源,跨平台,跨语言
- 协议可插拔:不同的服务可能需要使用不同的消息通信类型和编码机制,例如,JSON、XML和Thirft,所以协议应允许可插拔机制,还有负载均衡,服务发现,日志,监控等都支持可插拔机制
- 阻塞和非阻塞:支持客户端和服务器交换的消息序列的异步和同步处理。这对于在某些平台上扩展和处理至关重要
- 取消和超时:一次RPC操作可能是持久并且昂贵的,应该允许客户端设置取消RPC通信和对这次通信加上一个超时时间
- 拒绝:必须允许服务器通过在继续处理请求的同时拒绝新请求的到来并优雅地关闭。
- 流处理:存储系统依靠流和流控制来表达大型数据集,其他服务,如语音到文本或股票行情,依赖于流来表示与时间相关的消息序列
- 流控制:计算能力和网络容量在客户端和服务器之间通常是不平衡的。流控制允许更好的缓冲区管理,以及过度活跃的对等体提供对DOS的保护。
- 元数据交换:认证或跟踪等常见的跨领域问题依赖于不属于服务声明接口的数据交换。依赖于他们将这些特性演进到服务,暴露API来提供能力。
- 标准化状态码:客户端通常以有限的方式响应API调用返回的错误。应约束状态码名称空间,以使这些错误处理决策更加清晰。如果需要更丰富的特定领域的状态,则可以使用元数据交换机制来提供该状态。
- 互通性:报文协议(Wire Protocol)必须遵循普通互联网基础框架
gRPC 的一些特性
-
gRPC基于服务的思想:定义一个服务,描述这个服务的方法以及入参出参,服务器端有这个服务的具体实现,客户端保有一个存根,提供与服务端相同的服务。
-
gRPC默认采用protocol buffer作为IDL(Interface Description Lanage)接口描述语言,服务之间通信的数据序列化和反序列化也是基于protocol buffer的,因为protocol buffer的特殊性,所以gRPC框架是跨语言的通信框架(与编程语言无关性),也就是说用Java开发的基于gRPC的服务,可以用GoLang编程语言调用
-
gRPC同时支持同步调用和异步调用,同步RPC调用时会一直阻塞直到服务端处理完成返回结果,异步RPC是客户端调用服务端时不等待服务段处理完成返回,而是服务端处理完成后主动回调客户端告诉客户端处理完成
-
gRPC是基于http2协议实现的,http2协议提供了很多新的特性,并且在性能上也比http1提搞了许多,所以gRPC的性能是非常好的
-
gRPC并没有直接实现负载均衡和服务发现的功能,但是已经提供了自己的设计思路。已经为命名解析和负载均衡提供了接口
-
基于http2协议的特性:gRPC允许定义如下四类服务方法
- 一元RPC:客户端发送一次请求,等待服务端响应结构,会话结束,就像一次普通的函数调用这样简单
- 服务端流式RPC:客户端发起一起请求,服务端会返回一个流,客户端会从流中读取一系列消息,直到没有结果为止
- 客户端流式RPC:客户端提供一个数据流并写入消息发给服务端,一旦客户端发送完毕,就等待服务器读取这些消息并返回应答
- 双向流式RPC:客户端和服务端都一个数据流,都可以通过各自的流进行读写数据,这两个流是相互独立的,客户端和服务端都可以按其希望的任意顺序独写
gRPC的使用场景
-
低延迟,高度可扩展的分布式系统
-
开发与云服务器通信的客户端
-
设计一个准确,高效,且与语言无关的新协议时
-
分层设计,以实现扩展,例如。身份验证,负载平衡,日志记录和监控等
-
谷歌长期以来一直在gRPC中使用很多基础技术和概念。目前正在谷歌的几个云产品和谷歌面向外部的API中使用。Square,Netflix,CoreOS,Docker,CockroachDB,Cisco,Juniper Networks以及许多其他组织和个人也在使用它。
gRPC的数据封装和数据传输问题
这里我们主要介绍pb的工作方式,即怎样封装数据;
数据封装
gRPC 使用的是自己的封装方式 Protocol Buffer
简称ProtoBuf,是Google开发的一种跨语言、跨平台、可扩展的用于序列化数据协议。
下面是一个protoBuf 的样例
// XXXX.proto
// rpc服务的类 service关键字, Test服务类名
service Test {
// rpc 关键字,rpc的接口
rpc HowRpcDefine (Request) returns (Response) ; // 定义一个RPC方法
}
// message 类,c++ class
message Request {
//类型 | 字段名字| 标号
int64 user_id = 1;
string name = 2;
}
message Response {
repeated int64 ids = 1; // repeated 表示数组
Value info = 2; // 可嵌套对象
map<int, Value> values = 3; // 可输出map映射
}
message Value {
bool is_man = 1;
int age = 2;
}
以上是一个使用样例,包含方法定义、入参、出参。可以看出有几个明确的特点:
- 有明确的类型,支持的类型有多种
- 每个field会有名字
- 每个field有一个数字标号,一般按顺序排列(下文编解码会用到这个点)
- 能表达数组、map映射等类型
- 通过嵌套message可以表达复杂的对象
- 方法、参数的定义落到一个.proto 文件中,依赖双方需要同时持有这个文件,并依此进行编解码
protobuf作为一个以跨语言为目标的序列化方案,protobuf能做到多种语言以同一份proto文件作为约定,不用A语言写一份,B语言写一份,各个依赖的服务将proto文件原样拷贝一份即可。
但.proto文件并不是代码,不能执行,要想直接跨语言是不行的,必须得有对应语言的中间代码才行,中间代码要有以下能力:
- 将message转成对象,例如C++里是class,golang里是struct,需要各自表达后,才能被理解
- 需要有进行编解码的代码,能解码内容为自己语言的对象、能将对象编码为对应的数据
在完成数据封装之后,我们就准备好了将它传输出去,接下来就是数据传输了。
数据传输
grpc采用HTTP2.0,相对于HTTP1.0 在 更快的传输 和 更低的成本 两个目标上做了改进。有以下几个基本点:
- HTTP2 未改变HTTP的语义(如GET/POST等),只是在传输上做了优化
- 引入帧、流的概念,在TCP连接中,可以区分出多个request/response
- 一个域名只会有一个TCP连接,借助帧、流可以实现多路复用,降低资源消耗
- 引入二进制编码,降低header带来的空间占用
HTTP1.1核心问题在于:在同一个TCP连接中,没办法区分response是属于哪个请求,一旦多个请求返回的文本内容混在一起,则没法区分数据归属于哪个请求,所以请求只能一个个串行排队发送。这直接
导致了TCP资源的闲置。
HTTP2为了解决这个问题,提出了 流 的概念,每一次请求对应一个流,有一个唯一ID,用来区分不同的请求。基于流的概念,进一步提出了 帧 ,一个请求的数据会被分成多个帧,方便进行数据分割传输,每个帧都唯一属于某一个流ID,将帧按照流ID进行分组,即可分离出不同的请求。这样同一个TCP连接中就可以同时并发多个请求,不同请求的帧数据可穿插在一起,根据流ID分组即可。HTTP2.0基于这种二进制协议的乱序模式 (Duplexing),直接解决了HTTP1.1的核心痛点,通过这种复用TCP连接的方式,不用再同时建多个连接,提升了TCP的利用效率。
总结
传输使用 http2 协议,是在tcp链接完成之后,再在应用层发送时的一个协议,通过流 ID 和 帧报文的两个概念 解决了传输拥塞的问题。我们将这种方式称之为 tcp链接复用。
相关文章:

gRPC 的原理 介绍带你从头了解gRPC
gRPC 的原理 什么是gRPC gRPC的官方介绍是:gRPC是一个现代的、高性能、开源的和语言无关的通用 RPC 框架,基于 HTTP2 协议设计,序列化使用PB(Protocol Buffer),PB 是一种语言无关的高性能序列化框架,基于 HTTP2PB 保…...

Apriori算法
Apriori算法由R. Agrawal和R. Srikant于1994年在数据集中寻找布尔关联规则的频繁项集。该算法的名称是Apriori,因为它使用了频繁项集属性的先验知识。我们应用迭代方法或逐层搜索,其中k-频繁项集用于找到k1个项集。 为了提高频繁项集逐层生成的效率&…...

肖sir__linux讲解(2.1)
linux命令 cp 复制命令 a、cp 原文件名称 新文 件名称(不存在的文件) 案例:cp a k 截图: b.cp 原文件名称 原有文 件名称(存在的文件) 案例:cp a b 截图: c、cp 指定路径复制 格式ÿ…...

The ultimate UI kit and design system for Figma 组件库下载
Untitled UI 是世界上最大的 Figma UI 套件和设计系统。可以启动任何项目,为您节省数千小时,并祝您升级为专业设计师。 采用 100% 自动布局 5.0、变量、智能变体和 WCAG 可访问性精心制作。 900全局样式、变量:超级智能的全局颜色、排版和效…...

Selenium——利用input标签上传文件
Selenium利用input标签上传文件 完整流程 打开文件上传页面选择要上传的文件点击上传按钮确认文件上传成功介绍怎么方便的获取对应元素的Xpath或者Css 简单介绍 在使用Selenium进行浏览器自动化测试时,文件上传是一个常见的需求。而 标签就是实现文件上传功能的…...

C++初阶 日期类的实现(下)
目录 一、输入输出(>>,<<)重载的实现 1.1初始版 1.2友元并修改 1.2.1简单介绍下友元 1.2.2修改 1.3>>重载 二、条件判断操作符的实现 2.1操作符的实现 2.2!操作符的实现 2.3>操作符的实现 2.4>,<,<操作符的实现 三、日期-日期的实现 …...

大师学SwiftUI第16章 - UIKit框架集成
其它相关内容请见虚拟现实(VR)/增强现实(AR)&visionOS开发学习笔记 SwiftUI是一套新框架,因此并没有包含我们构建专业应用所需的所有工具。这意味着我们会需要求助于UIKit(移动设备)和AppKit(Mac电脑)等原…...

7.docker运行redis容器
1.准备redis的配置文件 从上一篇运行MySQL容器我们知道,需要给容器挂载数据卷,来持久化数据和配置,相应的redis也不例外。这里我们以redis6.0.8为例来实际说明下。 1.1 查找redis的配置文件redis.conf 下面这个网址有各种版本的配置文件供…...

unity教程
前言 伴随游戏行业的兴起,unity引擎的使用越来越普遍,本文章主要记录博主本人入门unity的相关记录大部分依赖siki学院进行整理。12 一、认识unity引擎? 1、Unity相关信息: Unity的诞生:https://www.jianshu.com/p/550…...
未定义与 ‘double‘ 类型的输入参数相对应的函数 ‘Link‘
报错 检查对函数"Link"得调用中是否缺失参数或参数数据类型不正确。 未定义与"double"类型的输入参数相对应的函数"Link"。 问题描述 网上搜了搜一般说是toolbox没有下载导致的,相当于调用的包本地没有。 但是我看看了 Robotics…...

为什么Transformer模型中使用Layer Normalization(Layer Norm)而不是Batch Normalization(BN)
❤️觉得内容不错的话,欢迎点赞收藏加关注😊😊😊,后续会继续输入更多优质内容❤️ 👉有问题欢迎大家加关注私戳或者评论(包括但不限于NLP算法相关,linux学习相关,读研读博…...

Vite - 配置 - 文件路径别名的配置
为什么要配置别名 别名的配置,主要作用是为了缩短代码中的导入路径。例如有如下的项目目录: project-name| -- src| -- a| --b| --c| --d| --e| -- abc.png| -- index.html| -- main.js如果想在 main.js 文件中使用 abc.png ,则使用的路径是 ࿱…...

phpStorm Xdebug调试 加FireFox浏览器
步骤1: [Xdebug] zend_extension“D:\phpstudy_pro\Extensions\php\php5.4.45nts\ext\php_xdebug.dll” xdebug.collect_params1 xdebug.collect_return1 xdebug.remote_enableOn xdebug.remote_hostlocalhost xdebug.remote_port9001 xdebug.remote_handlerdbgp ;…...

多维时序 | MATLAB实现PSO-BiGRU-Attention粒子群优化双向门控循环单元融合注意力机制的多变量时间序列预测
多维时序 | MATLAB实现PSO-BiGRU-Attention粒子群优化双向门控循环单元融合注意力机制的多变量时间序列预测 目录 多维时序 | MATLAB实现PSO-BiGRU-Attention粒子群优化双向门控循环单元融合注意力机制的多变量时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 …...

linux配置固定ip(两种方法)
首先刚下载的vm,刚创建的虚拟机,肯定是需要配置ip的 其次以前我的每次都是设置自动ip,这样每次登录都会自动获取ip地址,并且每次的ip都不相同。 ~方法: 开机登陆后 1)Cd /etc/sysconfig/network-scripts 2)Vi ifcf…...

什么是缓存雪崩、击穿、穿透?
背景 数据一般是存储于数据库中,数据库中的数据都是存在磁盘上的,磁盘读写的速度相较于内存或者CPU中的寄存器来说是非常慢的了。 如果用户的请求都直接访问数据库的话,请求数量一上来,数据库很容易就崩溃了,所以为了…...

可以通过电脑远程控制安卓设备的软件
有些时候,我们需要用电脑远程控制安卓设备,比如远程维护门店设备、安卓系统的户外广告牌等等。我们来探索和比较几款允许用户通过电脑远程控制安卓设备的软件。 1、Splashtop Business Splashtop 是一种多功能远程访问解决方案,以其高性能流…...

HP惠普暗影精灵9笔记本电脑OMEN by HP Transcend 16英寸游戏本16-u0000原厂Windows11系统
惠普暗影9恢复出厂开箱状态,原装出厂Win11-22H2系统ISO镜像 下载链接:https://pan.baidu.com/s/17ftbBHEMFSEOw22tnYvPog?pwd91p1 提取码:91p1 适用型号:16-u0006TX、16-u0007TX、16-u0008TX、16-u0009TX、16-u0017TX 原厂系…...
vue2+elementUI 仿照SPC开发CPK分析工具
源码地址请访问 Vue CPK分析工具页面设计源码(支持左右可拖拽和表格可编辑、复制粘贴)仿照SPC开发-CSDN博客...

云ES使用集群限流插件(aliyun-qos)
aliyun-qos插件是阿里云Elasticsearch团队自研的插件,能够提高集群的稳定性。该插件能够实现集群级别的读写限流,在关键时刻对指定索引降级,将流量控制在合适范围内。例如当上游业务无法进行流量控制时,尤其对于读请求业务,可根据aliyun-qos插件设置的规则,按照业务的优先…...

TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建
华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度
文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...