web性能优化之HTTP/2

web性能优化之HTTP/2

2021年03月04日 阅读:7 字数:2031 阅读时长:6 分钟

HTTP/2是 HTTP 协议的第二个主要版本,设计目标是:解决 HTTP1.X 中的性能问题,更有效的利用网络资源,减少网络应用的延迟,提高站点页面加载速度。

HTTP/2(超文本传输协议第2版),是 HTTP 协议的第二个主要版本,向下兼容 HTTP1.X,设计目标是:解决 HTTP1.X 中的性能问题,更有效的利用网络资源,减少网络应用的延迟,提高站点页面加载速度

HTTP历史

7d36f42cfcf0e3fc.png

HTTP/0.9

HTTP/0.9 是于 1991 年提出的,主要用于学术交流,需求很简单——用来在网络之间传递 HTML 超文本的内容,所以被称为超文本传输协议。整体来看,它的实现也很简单,采用了基于请求响应的模式,从客户端发出请求,服务器返回数据。

  • 因为 HTTP 都是基于 TCP 协议的,所以客户端先要根据 IP 地址、端口和服务器建立 TCP 连接,而建立连接的过程就是 TCP 协议三次握手的过程。

  • 建立好连接之后,会发送一个 GET 请求行的信息,如GET /index.html用来获取 index.html。

  • 服务器接收请求信息之后,读取对应的 HTML 文件,并将数据以 ASCII 字符流返回给客户端。

  • HTML 文档传输完成后,断开连接。

549906e676ae7efb.png

HTTP/1.0

万维网的高速发展带来了很多新的需求,而 HTTP/0.9 已经不能适用新兴网络的发展,所以这时就需要一个新的协议来支撑新兴网络,这就是 HTTP/1.0 诞生的原因。

  • 首先在浏览器中展示的不单是 HTML 文件了,还包括了 JavaScript、CSS、图片、音频、视频等不同类型的文件。因此支持多种类型的文件下载是 HTTP/1.0 的一个核心诉求,而且文件格式不仅仅局限于 ASCII 编码,还有很多其他类型编码的文件。为了让客户端和服务器能更深入地交流,HTTP/1.0 引入了请求头和响应头,它们都是以为 Key-Value 形式保存的,在 HTTP 发送请求时,会带上请求头信息,服务器返回数据时,会先返回响应头信息。
  • 为了减轻服务器的压力,在 HTTP/1.0 中提供了 Cache 机制,用来缓存已经下载过的数据。

  • 服务器需要统计客户端的基础信息,比如 Windows 和 macOS 的用户数量分别是多少,所以 HTTP/1.0 的请求头中还加入了用户代理的字段。

  • 有的请求服务器可能无法处理,或者处理出错,这时候就需要告诉浏览器服务器最终处理该请求的情况,这就引入了状态码。状态码是通过响应行的方式来通知浏览器的。

bcdef20b71dbfde1.png

HTTP/1.1

随着技术的继续发展,需求也在不断迭代更新,很快 HTTP/1.0 也不能满足需求了,所以 HTTP/1.1 又在 HTTP/1.0 的基础之上做了大量的更新。

  • 将短连接改为持久连接

  • 提供虚拟主机的支持

  • 对动态生成的内容提供了完美支持

HTTP/1.1的性能问题:

HTTP/1.1对带宽的利用率并不理想,这也是 HTTP/1.1 的一个核心问题。

带宽是指每秒最大能发送或者接收的字节数。我们把每秒能发送的最大字节数称为上行带宽,每秒能够接收的最大字节数称为下行带宽。之所以说 HTTP/1.1 对带宽的利用率不理想,是因为 HTTP/1.1 很难将带宽用满。比如我们常说的 100M 带宽,实际的下载速度能达到 12.5M/S,而采用 HTTP/1.1 时,也许在加载页面资源时最大只能使用到 2.5M/S,很难将 12.5M 全部用满。

原因:

  • TCP 的慢启动。一旦一个 TCP 连接建立之后,就进入了发送数据状态,刚开始 TCP 协议会采用一个非常慢的速度去发送数据,然后慢慢加快发送数据的速度,直到发送数据的速度达到一个理想状态,我们把这个过程称为慢启动。慢启动是 TCP 为了减少网络拥塞的一种策略,我们是没有办法改变的。

  • 同时开启了多条 TCP 连接,那么这些连接会竞争固定的带宽。想象一下,系统同时建立了多条 TCP 连接,当带宽充足时,每条连接发送或者接收速度会慢慢向上增加;而一旦带宽不足时,这些 TCP 连接又会减慢发送或者接收的速度。比如一个页面有 200 个文件,使用了 3 个 CDN,那么加载该网页的时候就需要建立 6 * 3,也就是 18 个 TCP 连接来下载资源;在下载过程中,当发现带宽不足的时候,各个 TCP 连接就需要动态减慢接收数据的速度。

  • HTTP/1.1 队头阻塞的问题。

bc30189fb0888bb0.png

HTTP/2特性

头部压缩

由于报文 Header 一般会携带“User Agent”“Cookie”“Accept”“Server”等许多固定的头字段,多达几百字节甚至上千字节,但 Body 却经常只有几十字节(比如 GET 请求),成了不折不扣的“大头儿子”。更要命的是,成千上万的请求响应报文里有很多字段值都是重复的,非常浪费,导致大量带宽消耗在了这些冗余度极高的数据上。HTTP/2 并没有使用传统的压缩算法,而是开发了专门的“HPACK”算法,在客户端和服务器两端建立“字典”,用索引号表示重复的字符串,还釆用哈夫曼编码来压缩整数和字符串,可以达到 50%~90% 的高压缩率。

二进制格式

HTTP/1 里使用纯文本形式的报文,它的优点是“一目了然”,用最简单的工具就可以开发调试,非常方便。但 HTTP/2 在这方面没有“妥协”,决定改变延续了十多年的现状,不再使用肉眼可见的 ASCII 码,而是向下层的 TCP/IP 协议“靠拢”,全面采用二进制格式。把原来的“Header+Body”的消息“打散”为数个小片的二进制“帧”(Frame),用“HEADERS”帧存放头数据、“DATA”帧存放实体数据。数据分帧后“Header+Body”的报文结构就完全消失了,协议看到的只是一个个的“碎片”。

379909523a50d6e4.png

多路复用

  1. 首先,浏览器准备好请求数据,包括了请求行、请求头等信息,如果是 POST 方法,那么还要有请求体。

  2. 这些数据经过二进制分帧层(stream)处理之后,会被转换为一个个带有请求 ID 编号的帧,通过协议栈将这些帧发送给服务器。

  3. 服务器接收到所有帧之后,会将所有相同 ID 的帧合并为一条完整的请求信息。

  4. 然后服务器处理该条请求,并将处理的响应行、响应头和响应体分别发送至二进制分帧层。

  5. 同样,二进制分帧层会将这些响应数据转换为一个个带有请求 ID 编号的帧,经过协议栈发送给浏览器。

  6. 浏览器接收到响应帧之后,会根据 ID 编号将帧的数据提交给对应的请求。

ab664682e431ac80.png

以及服务端推送(服务端主动推动客户端所需资源,减少请求次数),还有流量控制、请求优先级等。

开启HTTP/2

Nginx配置HTTP/2

Nginx的版本不能低于Nginx 1.10,编译的时候有http_v2_module和http_ssl_module模块,需要开启HTTPS

server {
      #开启HTTP2
      listen 443 ssl http2;
      #请填写绑定证书的域名
      server_name www.timelessq.com;
      #请填写证书文件的相对路径或绝对路径
      ssl_certificate  www.timelessq.com.crt;
      #请填写私钥文件的相对路径或绝对路径
      ssl_certificate_key www.timelessq.com.key; 
      ssl_session_timeout 5m;
      #添加需要的TLS协议配置
      ssl_protocols TLSv1.2 TLSv1.3; 
      #请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
      ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; 
      ssl_prefer_server_ciphers on;
}

检查请求使用的http协议

2ce78e38f04d2e87.png

推荐阅读

恰饭区

评论区 (0)

0/500

还没有评论,快来抢第一吧