文章目录
阅读HTTP2的RFC文档
RFC文档是请求注解文档(Requests for Comments,RFC)的简称,这是一种用于发布Internet标准和Internet其他正式出版物的网络文件或工作报告。
三个学习RFC文档的网站:
HTTP1.1 和 2 的区别
文心一言:
传输方式
- HTTP/2:采用二进制传输,进行二进制分帧和流传输。这种方式使得HTTP/2在传输过程中更加高效,因为二进制格式相比文本格式在解析上更为快速且减少了不必要的开销。
- HTTP/1.1:采用文本(报文)形式传输。HTTP/1.1的报文由文本形式的请求行、请求头(或响应头)、空行和请求体(或响应体)组成,这种方式虽然易于阅读和调试,但在传输效率上不如HTTP/2。
使用协议
- HTTP/2:基于HTTP+HPACK+Stream+TLS 1.2+TCP的协议栈。HPACK是一种头部压缩算法,用于减少HTTP/2消息中头部信息的大小,提高传输效率。
- HTTP/1.1:主要基于HTTP+TCP的协议栈。HTTP/1.1虽然也支持TLS加密(通过HTTPS),但其在协议栈中并未直接集成头部压缩等优化机制。
通信方式
- HTTP/2:支持全双工通信,即客户端和服务器都可以主动发起请求和响应,且请求和响应可以并行交错进行,互不干扰。这种通信方式大大提高了数据传输的效率和灵活性。
- HTTP/1.1:支持半双工通信,即在同一时间内,只有一方(客户端或服务器)可以主动发起请求或响应。虽然HTTP/1.1支持持久连接(即可以在一个TCP连接中发送多个请求和响应),但请求和响应仍然是按照顺序进行的。
压缩算法
- HTTP/2:使用HPACK算法对头部信息进行压缩。HPACK通过维护一个动态表来存储之前传输过的头部字段,对于重复的头部字段,只需传输其在表中的索引即可,从而大大减少了传输数据量。
- HTTP/1.1:不直接支持头部压缩。虽然可以通过一些扩展机制(如gzip)对请求体或响应体进行压缩,但头部信息仍然以原始文本形式传输。
其他特性
- 多路复用:HTTP/2支持在同一个TCP连接中并发处理多个请求和响应,而HTTP/1.1虽然也支持持久连接,但每个连接只能顺序地处理请求和响应。多路复用极大地提高了连接的利用率和吞吐量。
- 优先级:HTTP/2允许为每个数据流分配优先级和依赖关系,这使得服务器可以根据资源的可用性和客户端的需求来智能地处理请求和响应。
- 消息和帧:在HTTP/2中,消息由一系列帧组成,每个帧都包含帧头和数据部分。这种设计使得HTTP/2能够更灵活地处理数据流和传输错误。
HTTP2 和 HTTP3
如下图 HTTP2的二进制帧数据是在应用层层面解决冲突的,但是本质上在传输层并没有很大改善。
所以 HTTP3 在传输层上做了封装,将数据通过加一层 QUIC(本质上就是二进制帧数据+tcp在传输层上的引用),
后用了UDP更快?
Frame
帧是最小的传输单位,由9字节的头+变长的负载数据组成。
DATA
第6.1章节 “DATA Frame”(DATA帧)详细介绍了HTTP/2中用于传输数据的帧类型。以下是该章节的主要内容:
- 帧类型和用途:DATA帧(类型为0x00)用于传输与流相关联的任意字节序列。这些帧用于承载HTTP请求或响应消息的内容。
- 帧结构:DATA帧包含一个固定的9字节帧头,后跟一个可变长度的帧有效载荷。帧头包括帧长度、类型、标志、保留位、流标识符等字段。
- 帧标志:
- PADDED:当设置时,表示存在填充长度字段和填充内容。
- END_STREAM:当设置时,表示这是端点将为标识的流发送的最后一个帧,设置此标志会使流进入“half-closed”或“closed”状态。
- 填充(Padding):DATA帧可以包含填充字节,用于隐藏消息的大小,这是一种安全特性。填充字段包含填充长度,填充内容本身不包含应用语义价值,发送时应设置为零。
- 帧大小限制:DATA帧的有效载荷大小受接收方在SETTINGS_MAX_FRAME_SIZE设置中宣布的最大大小限制。帧大小必须在允许的范围内,否则接收方应以FRAME_SIZE_ERROR错误代码响应。
- 流量控制:DATA帧受流量控制,只能在流处于“open”或“half-closed (remote)”状态时发送。整个DATA帧有效载荷,包括填充长度和填充字段(如果存在),都计入流量控制。
- 帧错误处理:如果DATA帧的流不处于“open”或“half-closed (local)”状态,接收方应以STREAM_CLOSED错误代码响应。如果填充长度字段的值等于或大于帧有效载荷的长度,也应以PROTOCOL_ERROR错误代码处理。
- 帧序列:DATA帧可以独立发送,也可以与其他帧(如HEADERS、PUSH_PROMISE等)一起发送,以构成一个完整的HTTP消息。
- 安全性:填充的使用也与安全性相关,可以防止某些类型的攻击,如CRIME攻击。
第6.1章节为理解和实现HTTP/2中数据传输机制提供了详细的规范,确保数据帧的发送和接收符合协议要求,并与流量控制机制协同工作。
HEADERS
第6.2章节 “HEADERS Frame”(HEADERS帧)详细介绍了HTTP/2中用于传输消息头部的帧类型。以下是该章节的主要内容:
- 帧类型和用途:HEADERS帧(类型为0x01)用于开启一个新的流,并携带消息的头部部分。HEADERS帧可以携带HTTP请求或响应的头部字段,也可以携带尾部字段(trailers)。
- 帧结构:HEADERS帧包含一个固定的9字节帧头,后跟额外的字段,如填充长度(Pad Length)、填充标志(PADDED)、结束头部标志(END_HEADERS)、结束流标志(END_STREAM)等。
- 帧标志:
- PADDED:当设置时,表示存在填充长度字段和随后的填充字节。
- END_HEADERS:当设置时,表示这个帧包含了完整的头部块,后面不会跟随CONTINUATION帧。
- END_STREAM:当设置时,表示这是为特定流发送的最后一个帧,设置此标志会导致流进入“half-closed”或“closed”状态。
- 填充(Padding):HEADERS帧可以包含填充字节,用于保护消息内容或调整帧的大小。填充字节在发送时应该设置为零,接收方可以不验证填充但应将非零填充视为PROTOCOL_ERROR类型的错误。
- 优先级信息:虽然HEADERS帧中包含优先级信息的字段(PRIORITY),但这些字段在当前文档中已被废弃。这意味着不应再使用这些字段来传输优先级信息。
- 流关联:HEADERS帧与特定的流关联。如果接收到的HEADERS帧的流标识符为0x00,接收方应以PROTOCOL_ERROR错误代码响应。
- 帧大小限制:HEADERS帧的有效载荷大小受SETTINGS_MAX_FRAME_SIZE设置的限制。如果帧大小超出此限制,接收方应以FRAME_SIZE_ERROR错误代码响应。
- 连续帧(CONTINUATION):如果HEADERS帧没有包含完整的头部块,那么可以使用一个或多个CONTINUATION帧来继续传输剩余的头部块。最后一个CONTINUATION帧必须设置END_HEADERS标志。
- 消息头部压缩:HEADERS帧携带的头部字段使用HPACK压缩算法进行压缩,以减少传输开销。
- 安全性:HEADERS帧的设计考虑了安全性,例如通过限制可以传输的头部字段的大小来防止某些类型的攻击。
第6.2章节为理解和实现HTTP/2中头部传输机制提供了详细的规范,确保头部帧的发送和接收符合协议要求,并与流控制和消息头部压缩机制协同工作。
PRIORITY
第6.3章节 “PRIORITY Frame”(优先级帧)介绍了HTTP/2中用于控制流优先级的PRIORITY帧。以下是该章节的主要内容:
- 帧类型和用途:PRIORITY帧(类型为0x02)用于表达流的相对优先级。它允许端点指示哪些流应该优先处理。
- 帧格式:PRIORITY帧包含流标识符、独占标志(Exclusive)、流依赖标识符(Stream Dependency)和权重(Weight)等字段。
- 帧标志:PRIORITY帧不定义任何标志,因为优先级信息是单向的,仅由发送端决定。
- 帧内容:
- 流标识符:表示PRIORITY帧所关联的流。
- 独占标志:如果设置,表示该流应该独占其依赖的流,即该流是其依赖流的子流。
- 流依赖标识符:表示该流依赖的另一流的标识符。
- 权重:一个无符号的8位整数,表示该流相对于其他流的优先级权重。
- 帧大小:PRIORITY帧的长度固定为5个八位字节,不包含可变长度的帧有效载荷。
- 帧限制:PRIORITY帧可以在任何流状态中发送,包括处于"idle"(空闲)或"closed"(关闭)状态的流。但是,PRIORITY帧不能在构成单一消息块的连续帧之间发送。
- 帧处理:接收到PRIORITY帧的端点应该根据帧中的信息更新其对流的处理优先级。PRIORITY帧不会改变任何流的状态。
- 帧错误:如果PRIORITY帧的流标识符为0x00,或者帧长度不是5个八位字节,接收方应该以PROTOCOL_ERROR错误代码响应。
- 帧重要性:虽然PRIORITY帧在HTTP/2中是可选的,但正确使用它可以提高连接的性能,尤其是在处理多个并发流时。
第6.3章节强调了PRIORITY帧在HTTP/2中的作用,即允许端点表达和控制流的优先级,以优化资源分配和提高性能。然而,根据第5.3.2节的更新,HTTP/2的优先级信号机制已被废弃,因此本文档不再推荐使用PRIORITY帧。
RST_STREAM
第6.4章节 “RST_STREAM Frame”(RST_STREAM帧)详细介绍了HTTP/2中用于异常终止流的帧类型。以下是该章节的主要内容:
- 帧类型和用途:RST_STREAM帧(类型为0x03)用于立即终止一个流。它可以用来请求取消一个流或指示已经发生了错误条件。
- 帧结构:RST_STREAM帧包含流标识符和错误代码。帧不包含任何额外的数据或控制信息。
- 帧标志:RST_STREAM帧不定义任何标志。
- 帧内容:
- 流标识符:表示RST_STREAM帧所关联的流。
- 错误代码:一个32位的无符号整数,用于指示为何终止流。
- 帧大小:RST_STREAM帧的长度固定为4个字节,除了帧头之外。
- 帧处理:接收到RST_STREAM帧的端点必须立即将关联的流置于"closed"(关闭)状态,并停止发送任何进一步的帧到该流,除了PRIORITY帧。
- 帧错误:如果RST_STREAM帧的流标识符为0x00,或者帧长度不是4个字节,接收方应该以PROTOCOL_ERROR错误代码响应。
- 流状态变更:RST_STREAM帧完全终止引用的流,并导致其进入"closed"状态。接收到RST_STREAM帧后,接收方不得为该流发送额外的帧,但可以继续接收来自发送端的帧,直到它们被完全处理。
- 帧发送:RST_STREAM帧可以与处于任何状态的流关联。如果流处于"idle"(空闲)状态,接收到的RST_STREAM帧也应被处理。
- 帧重要性:RST_STREAM帧是HTTP/2中管理流状态的重要机制之一,它允许端点在检测到流无法继续进行时立即终止流。
第6.4章节强调了RST_STREAM帧在异常情况下的作用,即允许端点快速、明确地终止一个流,并确保双方都能识别流的终止状态。
SETTINGS
第6.5章节 “SETTINGS Frame”(SETTINGS帧)详细介绍了HTTP/2中用于配置端点通信参数的帧类型。以下是该章节的主要内容:
- 帧类型和用途:SETTINGS帧(类型为0x04)用于传达影响端点如何通信的配置参数,例如对等端的行为偏好和限制。SETTINGS帧也用于确认接收到这些设置。
- 帧结构:SETTINGS帧包含一个或多个设置参数,每个参数包括一个16位的设置标识符和一个32位的值。
- 帧标志:
- ACK(确认)标志:当设置时,表示该帧是确认接收和应用了对等端的SETTINGS帧。
- 帧内容:
- 长度:SETTINGS帧的长度必须为6的倍数,如果不是,接收方应该以FRAME_SIZE_ERROR错误代码响应。
- 流标识符:SETTINGS帧的流标识符必须为0x00,表示该帧适用于整个连接而不是单个流。
- 设置参数:定义了一系列的设置参数,如头部压缩表大小(SETTINGS_HEADER_TABLE_SIZE)、启用推送(SETTINGS_ENABLE_PUSH)、最大并发流(SETTINGS_MAX_CONCURRENT_STREAMS)、初始流量控制窗口大小(SETTINGS_INITIAL_WINDOW_SIZE)、最大帧大小(SETTINGS_MAX_FRAME_SIZE)和最大头部列表大小(SETTINGS_MAX_HEADER_LIST_SIZE)等。
- 设置同步:讨论了如何通过SETTINGS帧和ACK标志来同步设置,确保端点正确地应用了对方的设置。
- 设置应用:接收到SETTINGS帧的端点应立即应用更新的设置,并在处理完所有设置后发送一个带有ACK标志的SETTINGS帧作为确认。
- 设置限制:端点必须支持所有在本规范中定义的设置。对于未知或不支持的设置,端点应忽略它们。
- 错误处理:如果SETTINGS帧格式错误或不完整,或者端点接收到一个带有非0x00流标识符的SETTINGS帧,应该以PROTOCOL_ERROR错误代码响应。
- 安全性和性能:某些设置可能影响连接的安全性和性能,例如,初始流量控制窗口大小的不当设置可能导致拒绝服务攻击。
第6.5章节为理解和实现HTTP/2中的设置管理提供了详细的规范,确保端点能够正确地交换和应用连接配置参数。通过SETTINGS帧,端点可以调整它们的行为以适应对方的能力和偏好。
PUSH_PROMISE
第6.6章节 “PUSH_PROMISE Frame”(PUSH_PROMISE帧)详细介绍了HTTP/2中用于服务器推送功能的帧类型。以下是该章节的主要内容:
- 帧类型和用途:PUSH_PROMISE帧(类型为0x05)用于服务器向客户端提前通知它打算启动的流。这允许服务器在客户端请求之前推送资源,从而减少等待时间并提高性能。
- 帧结构:PUSH_PROMISE帧包含一个流的标识符,以及一个字段块片段,提供流的附加上下文信息。
- 帧标志:
- PADDED:当设置时,表示存在填充长度字段和随后的填充字节。
- END_HEADERS:当设置时,表示这个帧包含了完整的头部块,后面不会跟随任何CONTINUATION帧。
- 帧内容:
- 填充长度:如果PADDED标志被设置,这里会指定填充字节的长度。
- 承诺的流标识符:一个31位的无符号整数,标识服务器保留的流。
- 字段块片段:包含请求控制数据和头部部分。
- 帧限制:PUSH_PROMISE帧只能在处于"open"或"half-closed (remote)"状态的对端发起的流上发送。如果流标识符为0x00,接收方应该以PROTOCOL_ERROR错误代码响应。
- 服务器推送:PUSH_PROMISE帧用于实现服务器推送,服务器可以预测客户端可能需要的资源,并主动推送这些资源。
- 推送的接受与拒绝:客户端可以选择接受或拒绝推送的流。如果客户端不想接收推送的响应,可以发送一个RST_STREAM帧,引用PUSH_PROMISE中承诺的流标识符。
- 推送的安全性:承诺的请求必须是安全的(即幂等的),并且可以被缓存。客户端如果收到不安全或不可缓存的推送请求,应该以PROTOCOL_ERROR错误代码响应。
- 推送的顺序:承诺的流不需要按照它们被推送的顺序使用。PUSH_PROMISE帧仅用于保留流标识符供以后使用。
- 推送的状态变更:发送PUSH_PROMISE帧会改变连接状态,因为它可能改变字段部分压缩的状态,并为将来使用预留一个流。
第6.6章节强调了PUSH_PROMISE帧在HTTP/2中实现服务器推送功能的重要性,允许服务器利用其对客户端可能行为的了解来优化资源加载过程。然而,由于RFC 7540中定义的优先级信号系统未被广泛采用,本文档中简化了对推送功能的描述。
PING
第6.7章节 “PING Frame”(PING帧)详细介绍了HTTP/2中用于连接监测和测量最小往返时间(RTT)的帧类型。以下是该章节的主要内容:
- 帧类型和用途:PING帧(类型为0x06)是一种机制,用于测量从发送者到接收者并返回的最小往返时间,同时也可以用于确定一个空闲的连接是否仍然处于工作状态。
- 帧结构:PING帧具有固定的长度,包含8字节的不透明数据(Opaque Data),这些数据可以由发送端任意选择和使用。
- 帧标志:
- ACK:当设置时,表示这个PING帧是一个PING响应。发送端在响应PING请求时设置此标志。
- 帧内容:
- 帧负载包含8字节的不透明数据,接收方在收到不带ACK标志的PING帧时,必须以相同的负载数据发送带有ACK标志的PING响应。
- 帧限制:PING帧不与任何特定的流关联。如果接收到的PING帧流标识符字段的值不是0x00,接收方应该以PROTOCOL_ERROR错误代码响应。
- 帧大小:如果收到的PING帧长度字段的值不是8,接收方应该以FRAME_SIZE_ERROR错误代码响应。
- 帧发送和响应:PING帧可以从任一端点发送,接收方在收到不带ACK标志的PING帧时,必须以相同的负载数据和设置ACK标志发送响应。
- 优先级:PING响应应该被赋予比其他帧更高的优先级。
- 帧重要性:PING帧是HTTP/2中用于连接健康检查和性能监测的重要机制。
第6.7章节强调了PING帧在维护HTTP/2连接稳定性和性能方面的作用,允许端点检测连接的活性并测量连接的往返时间。这对于网络状况的监控和优化连接性能至关重要。
GOAWAY
第6.8章节 “GOAWAY Frame”(GOAWAY帧)详细介绍了HTTP/2中用于优雅关闭连接或信号严重错误的帧类型。以下是该章节的主要内容:
- 帧类型和用途:GOAWAY帧(类型为0x07)用于启动连接的关闭过程或信号严重错误情况。它允许端点在完成对之前建立的流的处理的同时,停止接受新的流。这有助于进行如服务器维护等管理操作。
- 帧结构:GOAWAY帧包含流标识符、最后流标识符(Last-Stream-ID)、错误代码和附加调试数据。
- 帧标志:GOAWAY帧不定义任何标志。
- 帧内容:
- 最后流标识符:指示发送端可能已处理或将要处理的最高编号的对等端发起的流。
- 错误代码:一个32位的值,指明了关闭连接的原因。
- 附加调试数据:提供额外的诊断信息,不具有语义价值。
- 帧限制:GOAWAY帧适用于整个连接,而不是特定的流。如果接收到的GOAWAY帧流标识符不是0x00,接收方应该以PROTOCOL_ERROR错误代码响应。
- 连接关闭:一旦发送了GOAWAY帧,发送端将忽略接收端在其上发起的、标识符高于包含的最后流标识符的流上发送的所有帧。接收方可以安全地重试使用新连接的、编号更高的流上的所有协议活动。
- 流重试:如果接收方在GOAWAY帧指示的最后流标识符之上发送了数据,那些流将不会被或将不会得到处理。接收方可以将这些流视为从未被创建,从而允许在新连接上稍后重试。
- 帧发送:在关闭连接之前,端点总是发送GOAWAY帧,以便远程对等端知道流是否已被部分处理。例如,如果HTTP客户端在服务器关闭连接的同时发送POST请求,服务器需要发送GOAWAY帧来指示它可能已经处理了哪些流。
- 错误处理:端点可能因对等端行为不当而选择不发送GOAWAY帧而直接关闭连接。
- 帧重要性:GOAWAY帧是HTTP/2中用于连接管理的关键机制之一,它允许端点在不丢失请求的情况下优雅地关闭连接。
第6.8章节强调了GOAWAY帧在HTTP/2连接管理中的作用,特别是在需要关闭连接或信号严重错误时,提供了一种优雅地终止连接的方法。
WINDOW_UPDATE
第6.9章节 “WINDOW_UPDATE Frame”(WINDOW_UPDATE帧)详细介绍了HTTP/2中用于流量控制的帧类型。以下是该章节的主要内容:
- 帧类型和用途:WINDOW_UPDATE帧(类型为0x08)用于实现流量控制机制。它允许接收方指示发送方在现有流量控制窗口的基础上,可以额外传输多少字节的数据。
- 帧结构:WINDOW_UPDATE帧包含一个保留位、流标识符和窗口大小增量(Window Size Increment)字段。帧的负载是一个无符号的31位整数,表示流量控制窗口的增加量。
- 帧功能:
- 流量控制窗口:每个发送方在每个流上都维护一个流量控制窗口,该窗口是一个简单的整数值,表示接收方允许发送方传输的数据量。
- 帧限制:
- 窗口大小增量的合法范围是1到2^31-1(2,147,483,647)字节。
- 如果WINDOW_UPDATE帧的窗口大小增量为0,接收方应该以PROTOCOL_ERROR错误代码响应。
- 帧应用范围:WINDOW_UPDATE帧可以针对特定流或整个连接。当针对特定流时,帧的流标识符指示受影响的流;当针对整个连接时,流标识符的值为"0"。
- 帧发送时机:当接收方消耗数据并释放流量控制窗口的空间时,它会发送WINDOW_UPDATE帧。接收方应避免发送窗口增量非常小的WINDOW_UPDATE帧。
- 帧处理:发送方在接收到WINDOW_UPDATE帧时,根据帧中指定的增量更新相应的流量控制窗口。
- 流量控制窗口管理:如果发送方收到的WINDOW_UPDATE帧导致流量控制窗口超过最大允许值(2^31-1),它应该根据情况终止流或连接,并发送相应的错误代码。
- 帧重要性:WINDOW_UPDATE帧是HTTP/2中流量控制机制的关键部分,它允许接收方控制发送方的数据传输速率,防止发送方耗尽接收方的缓冲区。
- 初始流量控制窗口大小:当HTTP/2连接首次建立时,默认的流和连接流量控制窗口大小为65,535字节。端点可以通过SETTINGS帧中的SETTINGS_INITIAL_WINDOW_SIZE设置来调整这个初始大小。
第6.9章节强调了WINDOW_UPDATE帧在维护HTTP/2连接的流量控制方面的重要性,确保了数据传输的稳定性和效率。通过正确地使用WINDOW_UPDATE帧,端点可以避免因流量控制不当而导致的连接问题。
CONTINUATION
第6.10章节 “CONTINUATION Frame”(CONTINUATION帧)详细介绍了HTTP/2中用于传输消息头部延续部分的帧类型。以下是该章节的主要内容:
- 帧类型和用途:CONTINUATION帧(类型为0x09)用于继续传输由HEADERS帧或PUSH_PROMISE帧开始的头字段块(field block)的剩余部分。它允许头字段块被分割并跨多个帧传输。
- 帧结构:CONTINUATION帧包含一个字段块片段(field block fragment),这是头字段块的一部分,可能由于大小限制或其他原因需要在多个帧中传输。
- 帧标志:
- END_HEADERS:当设置时,此标志表示该CONTINUATION帧结束了头字段块的传输序列。
- 帧内容:
- 字段块片段:CONTINUATION帧的有效载荷包含头字段块的一个片段。
- 帧限制:CONTINUATION帧必须紧跟在HEADERS、PUSH_PROMISE或另一个CONTINUATION帧之后,且这些帧不能设置END_HEADERS标志。如果接收到的帧类型或流标识符不符合这一规则,接收方应该以PROTOCOL_ERROR错误代码响应。
- 帧发送规则:发送方可以在需要时发送多个CONTINUATION帧,以传输整个头字段块。每个CONTINUATION帧可以携带头字段块的一个片段,直到整个头字段块被传输完毕。
- 帧接收规则:接收方必须按照发送顺序处理CONTINUATION帧,并在接收到带有END_HEADERS标志的帧时完成头字段块的重组。
- 帧重要性:CONTINUATION帧是HTTP/2中头字段压缩和多路复用机制的重要组成部分,它允许有效地传输大型或复杂的头字段集合。
- 帧错误处理:如果CONTINUATION帧的流标识符为0x00,或者如果接收方接收到的CONTINUATION帧不符合预期的序列,应该以PROTOCOL_ERROR错误代码响应。
第6.10章节强调了CONTINUATION帧在HTTP/2中传输头字段数据时的作用,特别是在处理需要分割的大头字段块时,确保了数据的连续性和完整性。