半小时搞懂 HTTP、HTTPS和HTTP2(下)

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: 半小时搞懂 HTTP、HTTPS和HTTP2(下)

HTTPS 连接建立过程

HTTPS 连接建立过程和 HTTP 差不多,区别在于 HTTP(默认端口 80) 请求只要在 TCP 连接建立后就可以发起,而 HTTPS(默认端口 443) 在 TCP 连接建立后,还需要经历 SSL 协议握手,成功后才能发起请求。

我知道肯定会有人不满足于简化版的 SSL 握手过程,所以我找了一篇文章SSL/TLS 握手过程详解,这篇文章非常详细的讲解了 SSL 握手的每一步骤。建议有兴趣的同学看一看。

HTTP/2

HTTP/2 是 HTTP/1.x 的扩展,而非替代。所以 HTTP 的语义不变,提供的功能不变,HTTP 方法、状态码、URL 和首部字段等这些核心概念也不变。

之所以要递增一个大版本到 2.0,主要是因为它改变了客户端与服务器之间交换数据的方式。HTTP 2.0 增加了新的二进制分帧数据层,而这一层并不兼容之前的 HTTP 1.x 服务器及客户端——是谓 2.0。

HTTP/2 连接建立过程

现在的主流浏览器 HTTP/2 的实现都是基于 SSL/TLS 的,也就是说使用 HTTP/2 的网站都是 HTTPS 协议的,所以本文只讨论基于 SSL/TLS 的 HTTP/2 连接建立过程。

基于 SSL/TLS 的 HTTP/2 连接建立过程和 HTTPS 差不多。在 SSL/TLS 握手协商过程中,客户端在 ClientHello 消息中设置 ALPN(应用层协议协商)扩展来表明期望使用 HTTP/2 协议,服务器用同样的方式回复。通过这种方式,HTTP/2 在 SSL/TLS 握手协商过程中就建立起来了。

HTTP/1.1 的问题

1. 队头阻塞

在 HTTP 请求应答过程中,如果出现了某种情况,导致响应一直未能完成,那后面所有的请求就会一直阻塞着,这种情况叫队头阻塞。

2. 低效的 TCP 利用

由于 TCP 慢启动机制,导致每个 TCP 连接在一开始的时候传输速率都不高,在处理多个请求后,才会慢慢达到“合适”的速率。对于请求数据量很小的 HTTP 请求来说,这种情况就是种灾难。

3. 臃肿的消息首部

HTTP/1.1 的首部无法压缩,再加上 cookie 的存在,经常会出现首部大小比请求数据大小还大的情况。

4. 受限的优先级设置

HTTP/1.1 无法为重要的资源指定优先级,每个 HTTP 请求都是一视同仁。

在继续讨论 HTTP/2 的新功能之前,先把 HTTP/1.1 的问题列出来是有意义的。因为 HTTP/2 的某些新功能就是为了解决上述某些问题而产生的。

二进制分帧层

HTTP/2 是基于帧的协议。采用分帧是为了将重要信息封装起来,让协议的解析方可以轻松阅读、解析并还原信息。

而 HTTP/1.1 是以文本分隔的。解析 HTTP/1.1 不需要什么高科技,但往往速度慢且容易出错。你需要不断地读入字节,直到遇到分隔符 CRLF 为止,同时还要考虑不守规矩的客户端,它只会发送 LF。

解析 HTTP/1.1 的请求或响应还会遇到以下问题:

  1. 一次只能处理一个请求或响应,完成之前不能停止解析。
  2. 无法预判解析需要多少内存。

HTTP/2 有了帧,处理协议的程序就能预先知道会收到什么,并且 HTTP/2 有表示帧长度的字段。

帧结构

+-----------------------------------------------+

|                 Length (24)                   |

+---------------+---------------+---------------+

|   Type (8)    |   Flags (8)   |

+-+-------------+---------------+-------------------------------+

|R|                 Stream Identifier (31)                      |

+=+=============================================================+

|                   Frame Payload (0...)                      ...

+---------------------------------------------------------------+

名称 长度 描述
Length 3 字节 表示帧负载的长度,取值范围为 (2 的 14 次方)至 (2 的 24 次方 - 1)。(2 的 14 次方) 16384 字节是默认的最大帧大小,如果需要更大的帧,必须在 SETTINGS 帧中设置
Type 1 字节 当前帧类型(见下表)
Flags 1 字节 具体帧类型的标识
R 1 位 保留位,不要设置,否则可能会带来严重的后果
Stream Identifier 31 位 每个流的唯一 ID
Frame Payload 长度可变 真实的帧内容,长度是在 Length 字段中设置的

由于 HTTP/2 是分帧的,请求和响应都可以多路复用,有助于解决类似类似队头阻塞的问题。

帧类型

名称 ID 描述
DATA 0x0 传输流的核心内容
HEADERS 0x1 包含 HTTP 首部,和可选的优先级参数
PRIORITY 0x2 指示或更改流的优先级和依赖
RST_STREAM 0x3 允许一端停止流(通常由于错误导致的)
SETTINGS 0x4 协商连接级参数
PUSH_PROMISE 0x5 提示客户端,服务器要推送些东西
PING 0x6 测试连接可用性和往返时延(RTT)
GOAWAY 0x7 告诉另一端,当前的端已结束
WINDOW_UPDATE 0x8 协商一端将要接收多少字节(用于流量控制)
CONTINUATION 0x9 用以扩展 HEADERS 模块

多路复用

在 HTTP/1.1 中,如果客户端想发送多个并行的请求,那么必须使用多个 TCP 连接。

而 HTTP/2 的二进制分帧层突破了这一限制,所有的请求和响应都在同一个 TCP 连接上发送:客户端和服务器把 HTTP 消息分解成多个帧,然后乱序发送,最后在另一端再根据流 ID 重新组合起来。

这个机制为 HTTP 带来了巨大的性能提升,因为:

  • 可以并行交错地发送请求,请求之间互不影响;
  • 可以并行交错地发送响应,响应之间互不干扰;
  • 只使用一个连接即可并行发送多个请求和响应;
  • 消除不必要的延迟,从而减少页面加载的时间;
  • 不必再为绕过 HTTP 1.x 限制而多做很多工作;

HTTP/2 规范对流的定义是:HTTP/2 连接上独立的、双向的帧序列交换。如果客户端想要发出请求,它会开启一个新流,然后服务器在这个流上回复。 由于有分帧,所以多个请求和响应可以交错,而不会互相阻塞。流 ID 用来标识帧所属的流。

客户端到服务器的 HTTP/2 连接建立后,通过发送 HEADERS 帧来启动新的流。如果首部需要跨多个帧,可能还会发送 CONTINUATION 帧。该 HEADERS 帧可能来自请求或响应。 后续流启动的时候,会发送一个带有递增流 ID 的新 HEADERS 帧。

消息

HTTP 消息泛指 HTTP 请求或响应,消息由一或多个帧组成,这些帧可以乱序发送,然后再根据每个帧首部的流 ID 重新组装。

一个消息至少由 HEADERS 帧(它初始化流)组成,并且可以另外包含 CONTINUATION 和 DATA 帧,以及其他的 HEADERS 帧。

HTTP/1.1 的请求和响应部分都分成消息首部和消息体两部分;HTTP/2 的请求和响应分成 HEADERS 帧和 DATA 帧。

优先级

把 HTTP 消息分解为很多独立的帧之后,就可以通过优化这些帧的交错和传输顺序,进一步提升性能。

通过 HEADERS 帧和 PRIORITY 帧,客户端可以明确地和服务器沟通它需要什么,以及它需要这些资源的顺序。具体来讲,服务器可以根据流的优先级,控制资源分配(CPU、内存、带宽),而在响应数据准备好之后,优先将最高优先级的帧发送给客户端。

流量控制

在同一个 TCP 连接上传输多个数据流,就意味着要共享带宽。标定数据流的优先级有助于按序交付,但只有优先级还不足以确定多个数据流或多个连接间的资源分配。

为解决这个问题,HTTP/2 为数据流和连接的流量控制提供了一个简单的机制:

  • 流量控制基于每一跳进行,而非端到端的控制;
  • 流量控制基于 WINDOW_UPDATE 帧进行,即接收方广播自己准备接收某个数据流的多少字节,以及对整个连接要接收多少字节;
  • 流量控制窗口大小通过 WINDOW_UPDATE 帧更新,这个字段指定了流 ID 和窗口大小递增值;
  • 流量控制有方向性,即接收方可能根据自己的情况为每个流乃至整个连接设置任意窗口大小;
  • 流量控制可以由接收方禁用,包括针对个别的流和针对整个连接。

HTTP/2 连接建立之后,客户端与服务器交换 SETTINGS 帧,目的是设置双向的流量控制窗口大小。除此之外,任何一端都可以选择禁用个别流或整个连接的流量控制。

服务器推送

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

为什么需要这样一个机制呢?通常的 Web 应用都由几十个资源组成,客户端需要分析服务器提供的文档才能逐个找到它们。那为什么不让服务器提前就把这些资源推送给客户端,从而减少额外的时间延迟呢?服务器已经知道客户端下一步要请求什么资源了,这时候服务器推送即可派上用场。

另外,客户端也可以拒绝服务器的推送。

首部压缩

HTTP/1.1 存在的一个问题就是臃肿的首部,HTTP/2 对这一问题进行了改进,可以对首部进行压缩。

在一个 Web 页面中,一般都会包含大量的请求,而其中有很多请求的首部往往有很多重复的部分。

例如有如下两个请求:

:authority: unpkg.zhimg.com
:method: GET
:path: /za-js-sdk@2.16.0/dist/zap.js
:scheme: https
accept: */*
accept-encoding: gzip, deflate, br
accept-language: zh-CN,zh;q=0.9
cache-control: no-cache
pragma: no-cache
referer: https://www.zhihu.com/
sec-fetch-dest: script
sec-fetch-mode: no-cors
sec-fetch-site: cross-site
user-agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)Chrome/80.0.3987.122 Safari/537.36
:authority: zz.bdstatic.com
:method: GET
:path: /linksubmit/push.js
:scheme: https
accept: */*
accept-encoding: gzip, deflate, br
accept-language: zh-CN,zh;q=0.9
cache-control: no-cache
pragma: no-cache
referer: https://www.zhihu.com/
sec-fetch-dest: script
sec-fetch-mode: no-cors
sec-fetch-site: cross-site
user-agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36

从上面两个请求可以看出来,有很多数据都是重复的。如果可以把相同的首部存储起来,仅发送它们之间不同的部分,就可以节省不少的流量,加快请求的时间。

HTTP/2 在客户端和服务器端使用“首部表”来跟踪和存储之前发送的键-值对,对于相同的数据,不再通过每次请求和响应发送。

下面再来看一个简化的例子,假设客户端按顺序发送如下请求首部:

Header1:foo
Header2:bar
Header3:bat

当客户端发送请求时,它会根据首部值创建一张表:

索引 首部名称
62 Header1 foo
63 Header2 bar
64 Header3 bat

如果服务器收到了请求,它会照样创建一张表。

当客户端发送下一个请求的时候,如果首部相同,它可以直接发送这样的首部块:

62 63 64

服务器会查找先前建立的表格,并把这些数字还原成索引对应的完整首部。

性能优化

使用 HTTP/2 代替 HTTP/1.1,本身就是一种巨大的性能提升。

这小节要聊的是在 HTTP/1.1 中的某些优化手段,在 HTTP/2 中是不必要的,可以取消的。

取消合并资源

在 HTTP/1.1 中要把多个小资源合并成一个大资源,从而减少请求。而在 HTTP/2 就不需要了,因为 HTTP/2 所有的请求都可以在一个 TCP 连接发送。

取消域名拆分

取消域名拆分的理由同上,再多的 HTTP 请求都可以在一个 TCP 连接上发送,所以不需要采取多个域名来突破浏览器 TCP 连接数限制这一规则了。

参考资料

更多文章,敬请关注

目录
相关文章
|
3月前
|
缓存 安全 网络协议
HTTP和HTTPS的区别有哪些?
本文简要总结了 HTTP 和 HTTPS 的区别,从概念、端口、连接方式、使用场景、安全性等多个角度进行了对比。HTTP 是无状态的、无连接的应用层协议,适用于一般性网站和性能要求较高的应用;HTTPS 则通过 SSL/TLS 层提供加密、认证和完整性保护,适用于涉及敏感信息和高安全性的场景。文章还讨论了两者在性能上的差异,包括握手和加密开销、缓存效果以及 HTTP/2 的多路复用技术。最终,根据具体需求选择合适的协议能够更好地平衡安全性和性能。
452 2
HTTP和HTTPS的区别有哪些?
|
2月前
|
前端开发 JavaScript 安全
前端性能调优:HTTP/2与HTTPS在Web加速中的应用
【10月更文挑战第27天】本文介绍了HTTP/2和HTTPS在前端性能调优中的应用。通过多路复用、服务器推送和头部压缩等特性,HTTP/2显著提升了Web性能。同时,HTTPS确保了数据传输的安全性。文章提供了示例代码,展示了如何使用Node.js创建一个HTTP/2服务器。
69 3
|
7天前
|
应用服务中间件 Linux 网络安全
nginx安装部署ssl证书,同时支持http与https方式访问
为了使HTTP服务支持HTTPS访问,需生成并安装SSL证书,并确保Nginx支持SSL模块。首先,在`/usr/local/nginx`目录下生成RSA密钥、证书申请文件及自签名证书。接着,确认Nginx已安装SSL模块,若未安装则重新编译Nginx加入该模块。最后,编辑`nginx.conf`配置文件,启用并配置HTTPS服务器部分,指定证书路径和监听端口(如20000),保存后重启Nginx完成部署。
158 7
|
10天前
|
安全 算法 网络安全
HTTP和HTTPS的区别
本文介绍HTTP与HTTPS的区别、HTTPS链接建立过程及常见加密算法。HTTP为明文传输,易被窃听;HTTPS通过SSL/TLS协议加密,确保数据安全。HTTPS使用端口443,提供认证机制。文中还详细讲解了对称加密(如AES、DES)和非对称加密(如RSA、ECC)算法的特点及应用场景。
|
2月前
|
Web App开发 Linux 应用服务中间件
【DrissionPage】Linux上如何将https改为http
通过上述步骤,可以在Linux上将DrissionPage从HTTPS改为HTTP。关键在于修改DrissionPage配置、代码中的HTTPS设置、URL以及Web服务器配置,确保所有部分都正确使用HTTP协议。通过合理配置和测试,能够确保系统在HTTP环境下稳定运行。
42 1
|
2月前
|
缓存 安全 网络安全
HTTP/2与HTTPS在Web加速中的应用
HTTP/2与HTTPS在Web加速中的应用
|
16天前
|
安全 网络安全 数据安全/隐私保护
第六问:http和https区别与联系
HTTP 和 HTTPS 是现代网络通信中的两种重要协议。HTTP 是明文传输协议,无加密功能;HTTPS 在 HTTP 基础上加入 SSL/TLS 加密层,提供数据加密、身份验证和数据完整性保障。HTTP 适用于非敏感信息传输,如新闻网站;HTTPS 适用于在线支付、账户登录等需要保护用户数据的场景。
27 0
|
2月前
|
前端开发 JavaScript 数据库
https页面加载http资源的解决方法
https页面加载http资源的解决方法
62 5
|
2月前
|
前端开发 安全 应用服务中间件
前端性能调优:HTTP/2与HTTPS在Web加速中的应用
【10月更文挑战第26天】随着互联网的快速发展,前端性能调优成为开发者的重要任务。本文探讨了HTTP/2与HTTPS在前端性能优化中的应用,介绍了二进制分帧、多路复用和服务器推送等特性,并通过Nginx配置示例展示了如何启用HTTP/2和HTTPS,以提升Web应用的性能和安全性。
42 3
|
2月前
|
前端开发 JavaScript 数据库
https页面加载http资源的解决方法
https页面加载http资源的解决方法
67 4