@@ -196,14 +196,15 @@ HTTP 状态码用于描述 HTTP 请求的结果,比如 2xx 就代表请求被
196
196
197
197
- ** 多路复用(Multiplexing)** :HTTP/2.0 在同一连接上可以同时传输多个请求和响应(可以看作是 HTTP/1.1 中长链接的升级版本),互不干扰。HTTP/1.1 则使用串行方式,每个请求和响应都需要独立的连接,而浏览器为了控制资源会有 6-8 个 TCP 连接的限制。这使得 HTTP/2.0 在处理多个请求时更加高效,减少了网络延迟和提高了性能。
198
198
- ** 二进制帧(Binary Frames)** :HTTP/2.0 使用二进制帧进行数据传输,而 HTTP/1.1 则使用文本格式的报文。二进制帧更加紧凑和高效,减少了传输的数据量和带宽消耗。
199
+ - ** 队头阻塞** :HTTP/2 引入了多路复用技术,允许多个请求和响应在单个 TCP 连接上并行交错传输,解决了 HTTP/1.1 应用层的队头阻塞问题,但 HTTP/2 依然受到 TCP 层队头阻塞 的影响。
199
200
- ** 头部压缩(Header Compression)** :HTTP/1.1 支持` Body ` 压缩,` Header ` 不支持压缩。HTTP/2.0 支持对` Header ` 压缩,使用了专门为` Header ` 压缩而设计的 HPACK 算法,减少了网络开销。
200
201
- ** 服务器推送(Server Push)** :HTTP/2.0 支持服务器推送,可以在客户端请求一个资源时,将其他相关资源一并推送给客户端,从而减少了客户端的请求次数和延迟。而 HTTP/1.1 需要客户端自己发送请求来获取相关资源。
201
202
202
203
HTTP/2.0 多路复用效果图(图源: [ HTTP/2 For Web Developers] ( https://blog.cloudflare.com/http-2-for-web-developers/ ) ):
203
204
204
205
![ HTTP/2 Multiplexing] ( https://oss.javaguide.cn/github/javaguide/cs-basics/network/http2.0-multiplexing.png )
205
206
206
- 可以看到,HTTP/2.0 的多路复用使得不同的请求可以共用一个 TCP 连接,避免建立多个连接带来不必要的额外开销,而 HTTP/1.1 中的每个请求都会建立一个单独的连接
207
+ 可以看到,HTTP/2 的多路复用机制允许多个请求和响应共享一个 TCP 连接,从而避免了 HTTP/1.1 在应对并发请求时需要建立多个并行连接的情况,减少了重复连接建立和维护的额外开销。而在 HTTP/1.1 中,尽管支持持久连接,但为了缓解队头阻塞问题,浏览器通常会为同一域名建立多个并行连接。
207
208
208
209
### HTTP/2.0 和 HTTP/3.0 有什么区别?
209
210
@@ -232,6 +233,29 @@ HTTP/1.0、HTTP/2.0 和 HTTP/3.0 的协议栈比较:
232
233
233
234
关于 HTTP/1.0 -> HTTP/3.0 更详细的演进介绍,推荐阅读[ HTTP1 到 HTTP3 的工程优化] ( https://dbwu.tech/posts/http_evolution/ ) 。
234
235
236
+ ### HTTP/1.1 和 HTTP/2.0 的队头阻塞有什么不同?
237
+
238
+ HTTP/1.1 队头阻塞的主要原因是无法多路复用:
239
+
240
+ - 在一个 TCP 连接中,资源的请求和响应是按顺序处理的。如果一个大的资源(如一个大文件)正在传输,后续的小资源(如较小的 CSS 文件)需要等待前面的资源传输完成后才能被发送。
241
+ - 如果浏览器需要同时加载多个资源(如多个 CSS、JS 文件等),它通常会开启多个并行的 TCP 连接(一般限制为 6 个)。但每个连接仍然受限于顺序的请求-响应机制,因此仍然会发生 ** 应用层的队头阻塞** 。
242
+
243
+ 虽然 HTTP/2.0 引入了多路复用技术,允许多个请求和响应在单个 TCP 连接上并行交错传输,解决了 ** HTTP/1.1 应用层的队头阻塞问题** ,但 HTTP/2.0 依然受到 ** TCP 层队头阻塞** 的影响:
244
+
245
+ - HTTP/2.0 通过帧(frame)机制将每个资源分割成小块,并为每个资源分配唯一的流 ID,这样多个资源的数据可以在同一 TCP 连接中交错传输。
246
+ - TCP 作为传输层协议,要求数据按顺序交付。如果某个数据包在传输过程中丢失,即使后续的数据包已经到达,也必须等待丢失的数据包重传后才能继续处理。这种传输层的顺序性导致了 ** TCP 层的队头阻塞** 。
247
+ - 举例来说,如果 HTTP/2 的一个 TCP 数据包中携带了多个资源的数据(例如 JS 和 CSS),而该数据包丢失了,那么后续数据包中的所有资源数据都需要等待丢失的数据包重传回来,导致所有流(streams)都被阻塞。
248
+
249
+ 最后,来一张表格总结补充一下:
250
+
251
+ | ** 方面** | ** HTTP/1.1 的队头阻塞** | ** HTTP/2.0 的队头阻塞** |
252
+ | -------------- | ---------------------------------------- | ---------------------------------------------------------------- |
253
+ | ** 层级** | 应用层(HTTP 协议本身的限制) | 传输层(TCP 协议的限制) |
254
+ | ** 根本原因** | 无法多路复用,请求和响应必须按顺序传输 | TCP 要求数据包按顺序交付,丢包时阻塞整个连接 |
255
+ | ** 受影响范围** | 单个 HTTP 请求/响应会阻塞后续请求/响应。 | 单个 TCP 包丢失会影响所有 HTTP/2.0 流(依赖于同一个底层 TCP 连接) |
256
+ | ** 缓解方法** | 开启多个并行的 TCP 连接 | 减少网络掉包或者使用基于 UDP 的 QUIC 协议 |
257
+ | ** 影响场景** | 每次都会发生,尤其是大文件阻塞小文件时。 | 丢包率较高的网络环境下更容易发生。 |
258
+
235
259
### HTTP 是不保存状态的协议, 如何保存用户状态?
236
260
237
261
HTTP 是一种不保存状态,即无状态(stateless)协议。也就是说 HTTP 协议自身不对请求和响应之间的通信状态进行保存。那么我们如何保存用户状态呢?Session 机制的存在就是为了解决这个问题,Session 的主要作用就是通过服务端记录用户的状态。典型的场景是购物车,当你要添加商品到购物车的时候,系统不知道是哪个用户操作的,因为 HTTP 协议是无状态的。服务端给特定的用户创建特定的 Session 之后就可以标识这个用户并且跟踪这个用户了(一般情况下,服务器会在一定时间内保存这个 Session,过了时间限制,就会销毁这个 Session)。
@@ -406,6 +430,7 @@ DNS 服务器自底向上可以依次分为以下几个层级(所有 DNS 服务
406
430
### DNS 劫持了解吗?如何应对?
407
431
408
432
DNS 劫持是一种网络攻击,它通过修改 DNS 服务器的解析结果,使用户访问的域名指向错误的 IP 地址,从而导致用户无法访问正常的网站,或者被引导到恶意的网站。DNS 劫持有时也被称为 DNS 重定向、DNS 欺骗或 DNS 污染。
433
+
409
434
## 参考
410
435
411
436
- 《图解 HTTP》
0 commit comments