【QCon】精华内容上线92%,全面覆盖“人工智能+”的典型案例!>>> 了解详情
写点什么

HTTP/2 探索第一篇——概念

  • 2019-08-22
  • 本文字数:3490 字

    阅读完需:约 11 分钟

HTTP/2探索第一篇——概念

一、现状

1. 网络性能

现在网络优化的瓶颈是什么?你可能会说,带宽。也许在 2014 年前,决定性能的关键是带宽,但是在今天以及以后,瓶颈都不会是带宽,而是延迟;



从图中可以看出,随着带宽的增长,页面加载时间(PLT Page Load Time)在 1Mbps 到 3Mbps 的区间得到了很大的改善,但是再提高带宽,带来的提升就很小了,属于非线性改善;反观延迟,延迟(这里是指多个 RTT 时间相加的总和)的改善对于页面加载时间是属于线性改善;


HTTP/1.1 TCP 连接是需要三次握手的,同时,多个 TCP 连接也会给服务器带来资源的消耗,在 HTTP/1.1 中,每个请求回复都是一次 TCP 连接(未开启 Keep-Alive 的情况下),并且,同时传输多个资源时,会有队首阻塞的问题,造成网络资源无法有效利用;

2. 安全

对于大多数人来说,下图的情况几乎都有遇到过(电脑或手机里)。万恶的运营商或者网络接入 WiFi 提供商劫持我们的网络,修改网络的内容,给我们带来了很大的困扰;


二、HTTP/2.0

现在,HTTP/2.0 出现了。其实 HTTP/2.0 是支持 Clear Text 版和 Over TLS 版,由于现有支持 HTTP/2.0 的浏览器都是实现的 Over TLS 版,故本文的 HTTP/2.0 都是讲的是 HTTPS 版 HTTP/2.0;

1. Clear Text 版:

客户端向服务端请求(假设此时 scheme 是 HTTP),带有以下头:


Upgrade: h2c


HTTP2-Settings


服务器端返回:


101 状态码,转换协议;


Connection: Upgrade


Upgrade: h2c 或者 200/404

2. HTTP/2.0 Over TLS 版:

客户端向服务器端请求


TLS + ALPN(Application Layer Protocol Negotiation)/NPN


服务器端返回:


TLS 握手 并返回支持的 HTTP 协议;


a. TLS 握手详细过程



b. ALPN 协商过程


参考 TLS 握手过程图,下面是增加 ALPN 协商的具体过程:


客户端添加一个 ProtocolNameList 字段,包含支持的 HTTP 协议到 ClientHello 消息中;


服务器端查看 ProtocolNameList 字段后通过 ServerHello 消息返回 ProtocolName 字段,表明被选定的协议;


通过实现 ALPN,不再需要单独请求一次服务器带上 Upgrade: h2c;


c. False Start


通常情况下,使用 ALPN 会搭配使用 False Start,客户端在完成 TLS 握手前提前发送加密后的应用数据,将两次 RTT TLS 握手减少为一次;不过需要同时支持 ALPN(NPN 已经很少用啦)和前向安全性;


d. HSTS


HTTP Strict Transport Security(简称为 HSTS)是一个安全功能,告诉浏览器只能通过 HTTPS 访问当前资源,禁止 HTTP 方式。


如果用户输入域名www.qq.com,浏览器首先会去请求http://www.qq.com,请求过程是明文非加密的,此时容易被中间人攻击,让网路恶意中间商直接接触到用户信息;而 HSTS 是用户请求时,服务器告诉客户端,下次来请求直接请求 https://,而不要再请求服务器来跳转到 https;


同时,开启 HSTS 后,如果证书认证不通过(比如遭到中间人攻击),浏览器此时强制无法打开该网站;

3. 名词解释

流(Stream):一个 Stream 是包含一条或多条信息,ID 和优先级的双向通道;


消息(Message):消息由帧组成;


帧(Frame):帧有不同的类型,并且是混合的。他们通过 stream id 被重新组装进消息中;

4. 概念解释

a. 二进制帧



HTTP2 的二进制帧是 9 字节(72 bit)


长度:24bit,也就是理论上可以携带 2^24 字节的数据。但通常由于 SETTINGS_MAX_FRAME_SIZE 的设置,不能发送超过 2^14(16384)字节的数据;


类型:8bit,决定了该帧的类型;


DATA : 数据帧


HEADERS : 头部帧


PRIORITY : 设置流的优先级


RST_STREAM : 终止流


SETTINGS : 设置连接参数


PUSH_PROMISE : 服务器推送模拟请求帧


PING : 用来计算 RTT 时间和看是否服务器挂了的 Stream


GOAWAY : 告诉对方停止再向当前连接创建 stream


WINDOW_UPDATE : 流量控制


保留字段:1bit,一般为 0;


Stream ID:31bit,Stream 标识,理论上可以有 2147483648,超过这么多 stream 怎么办呢?


如果是客户端无法再创建新的 stream id,可以直接创建新的 TCP 连接,stream id 被重置;


如果是服务器端无法再创建新的 stream id,服务器将会给客户端发一个 GOAWAY 帧,客户端无法再向该服务器创建 stream,不得不新建 TCP 连接;

5. 新特性

多路复用


头部压缩


资源优先级/依赖关系


流量控制


Server Push(客户端请求一个路径时,服务器推送一个资源给客户端)


a. 多路服用



HTTP/2.0 中,数据在发送端被切分为更小的数据帧用以高效利用链接;


HTTP 1.1 时代,再不开启 Keep-alive 的情况下,每一个请求会占用一个 TCP 连接,而 HTTP/2 将请求和响应消息拆分为各自独立的帧,交错的发送,然后再在接收端重新装配组合。有什么好处呢?


交错的多个请求/响应之间互现不会被阻塞


HTTP/1.1 时代的 Keep-alive 也是保持同一个 TCP 连接,但是由于请求/接收有先后,后面的请求资源会被前面的资源阻塞(没收到响应时不会发新的请求),如下图最左和最右边所示,即便是相比 HTTP 管道,优化也是巨大的:



减少了不必要的延时,改善了网路的利用率(多路复用和资源优先级/依赖关系搭配使用,使得页面重度依赖的资源优先传输);


b. 头部压缩


HTTP/2.0 使用 HPACK 来给头部压缩;


值通过霍夫曼编码;


之前发送的值都被索引起来,之后使用时发现之前发送过该 Header 字段,并且值相同,就会沿用之前的索引来指代那个 Header 值;


Cookies:在 HTTP/2.0 中,Cookie 也将会变为键值对索引起来,而不是一长串字符串;


可以看看我们组 dream 同学的 HTTP/2.0 之特性科普篇——头部压缩,里面有截图部分的数据讲述压缩后的效果;



这里需要讲解一下伪头部字段:


请求:


:authority


:method


:path


:scheme


响应:


:status


所有的伪头部字段都是在所有 Header 的前部;


c. 资源优先级/依赖关系


资源优先级/依赖关系通过 stream 权重和 dependency 来设置;



通过上图可以看到,有一列是叫作 Priority,初始设置是根据 Content-type 来设置优先级的,比如 HTML 是 Highest,CSS 是 High,然后 JS 是 Medium;


Stream 权重值可以设置为 1 到 256 之间;


Stream 可以明确的表示依赖关系;


注意,一定要理解权重和依赖,权重值和依赖关系是作为带宽资源/服务器/客户端处理资源的建议值,但并不能保证他们有特定的传输顺序。让我们来看一张 HTTP/2.0 的依赖关系和权重图:



HTTP/2.0 中的 stream 都默认是依赖于一个根 stream(其实不存在)。权重值是针对同级来计算的,不同级是不用来计算的;


d. 流量控制


与 TCP 的流量控制类似,不过 HTTP/2.0 的流量控制可以到具体帧,而 TCP 是 TCP 连接层面上的。注意:流量控制目前只对 DATA 帧有效!流量控制的算法没有具体要求使用哪一种,但是大概实现的功能是这样的:


两端收发保有一个流量控制(window)窗口;


发送端每发送一个 DATA 帧,就把窗口的大小递减,递减量为这个帧的大小,要是窗口大小小于该帧的大小,那么这个帧就必须被拆分。如果窗口值等于 0,就不能发送任何帧。流量控制的初始默认窗口值大小为 65535 字节(理论上可以设置 2^31-1 字节也就是 2147483647 字节大小的窗口值)。


接收端可以通过发送 WINDOW_UPDATE 帧给发送端,发送端以帧内指定的窗口大小增量加到窗口大小限制上。


e. Server Push


Server Push 的资源同样需要遵守同源策略,通过:authority 来判断;



如 Demo 里所示,如果在服务器端设置当请求 Path/examples/dashboard 时就推送/examples/dashboard/d3.js,现在我们来看抓包:



说明:


当客户端请求服务器时(此时的请求路径已经设置好推送),服务器发回一个 PUSH_PROMISE 和两个 HEADERS Frame,从 Stream Identifier 可以看出,第一个 HEADERS 的 Stream ID 是 1,也就是复用请求的 Stream 来返回(这是 HTML 文件的返回响应 Header)。第二个 HEADERS 就是推送文件的响应 Header。


根据定义,由客户端初始化发起的 Stream 的标识符是奇数,由服务器端初始化发起的 Stream 是偶数,图中可以体现;


那么 Stream 1 和 Stream 2 的顺序如何保证呢?说明文档里有这样一句话:


Pushed streams initially depend on their associated stream.


也就是说,服务器将要推送的资源依赖于触发推送的请求,根据 Stream 依赖的功能,只有被依赖的 stream 加载完后才会去加载接下来的 stream;


Server Push 有什么好处呢:


推送的资源可以被客户端缓存;


推送的资源可以被不同的页面复用;


推送资源也是支持多路复用的;


推送资源可以被客户端拒绝掉(客户端接收到 PUSH_PROMISE 后,可以选择发送 RST_PROMISE 来拒绝接收,告诉服务器端不要再发送了,当然,此时可能已经有部分内容已经发送过来了);


同时,Server Push 配合流量控制,可以实现很多很神奇的功能,这里卖个关子,然后会在下一篇讲解 :)


本文转载自公众号小时光茶舍(ID:gh_7322a0f167b5)。


原文链接:


https://mp.weixin.qq.com/s/Y1x0GUkfRbWEz6YsJrMTAQ


2019-08-22 19:063304

评论

发布
暂无评论
发现更多内容

面试中必问的JVM应该怎么学(面试题含答案)

猿灯塔

PHP实现一致性哈希算法

任小龙

架构师训练营 -week5 命题作业

J.Smile

极客大学架构师训练营

LeetCode | 7. Merge Two Sorted Lists 合并两个有序列表

Puran

Python C# 算法 LeetCode

游戏夜读 | 简单认识一下爬虫

game1night

一文搞懂分布式消息中间件设计

小隐乐乐

消息队列

唯一路径的动态规划解法,阿里巴巴架构演化路径 John 易筋 ARTS 打卡 Week 07

John(易筋)

动态规划 ARTS 打卡计划 系统架构演化 唯一路径

ARTS|Week 6 合并有序列表、团队、MIME类型和IIS

Puran

LeetCode ARTS 打卡计划

架构师训练营第五周学习总结

张明森

在Windows上使用IIS来托管站点

Puran

windows IIS Server

一篇告诉你什么是Spring

JavaPub

spring

Python设计模式 单例模式

早睡蟒

Python 面向对象 设计模式 单例模式

架构师训练营总结-20200705

caibird1984

极客大学架构师训练营

如何站在架构师的角度做框架

小新

Java 集合 框架

80%会问到的18个Dubbo面试题,快来看看你都掌握了吗

小新

Java 程序员 架构 面试 dubbo

Git【入门】这一篇就够了

JavaPub

spring

第一个Spring程序(代码篇)

JavaPub

spring

分布式系统架构设计 - 一致性hash算法及其改进

常平

分布式 架构设计

Java架构-Apache POI Excel

猿灯塔

ConcurrentHashMap里面也有死循环

无予且行

Java jdk 面试 jdk8

第五周作业

秦宝齐

学习

一致性Hash算法——架构师训练营第5周

架构 极客大学架构师训练营 一致性Hash算法 第5周作业 负载均衡算法

总结

Mr.Monkey

ARTS Week6

丽子

极客大学架构师训练营 系统架构 消息队列 数据库备份 第10课 听课总结

John(易筋)

负载均衡 极客时间 极客大学 极客大学架构师训练营 消息队列

分布式系统架构设计 - 从CAP到PACELC

常平

架构 分布式

授权专利争夺正当时

CECBC

数据隐私 授权专利 平台应用服务

区块链+金融赋能高原特色农业重点产业

CECBC

打破信息孤岛 区块链+咖啡 特色农业 咖云链

从“金 木 水 火 土”到分布式系统架构设计

常平

分布式 架构设计

程序人生 | 春风得意马蹄疾,一日看尽长安花

YourBatman

Java 程序员 程序人生

架构师训练营 第 5 周总结

Lingjun

极客大学架构师训练营

HTTP/2探索第一篇——概念_安全_张浩然_InfoQ精选文章