写点什么

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:063439

评论

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

Serverless 工程实践 | 快速搭建 Kubeless 平台

Serverless Devs

k8s 架构设计 框架搭建 框架学习

Serverless 下的微服务实践

Serverless Devs

阿里云 Serverless 架构 微服务

Serverless 架构模式及演进

Serverless Devs

Serverless 架构设计

2021 大厂面试题之 mysql 篇

小麦

MySQL 面试题 大厂

全面解读!构建边云一体的智能应用技术实践

百度开发者中心

最佳实践 方法论 边缘计算 前沿科技

为什么建议大家使用 Linux 开发?爽(外加七个感叹号)

Java 程序员 后端

二维码扫码登录是什么原理?

Java 程序员 后端

云原生时代下,容器安全的“四个挑战”和“两个关键

Java 程序员 后端

京东T7架构师用470页就把微服务架构原理与开发实战文档讲完了

Java 程序员 后端

CSS页面设计稿构思与实现(三)之UI组件

Augus

CSS 11月日更

五分钟带你了解Seata分布式事务

Java 程序员 后端

为了加快速度,Redis都做了哪些“变态”设计

Java 程序员 后端

主流的消息队列MQ比较,详解MQ的4类应用场景

Java 程序员 后端

这一次,中国CRM站到风口上了吗?

ToB行业头条

CRM

五、redis配置信息以及常用命令

Java 程序员 后端

五分钟学会做一个在线抽奖系统,手把手教你抽奖还学不会嘛?

Java 程序员 后端

docker基础

小麦

为什么你的insert就死锁了

Java 程序员 后端

京东T7架构师手写的10万字Spring Boot详细学习笔记+源码免费下载

Java 程序员 后端

模块三

侠客行

架构实战 「架构实战营」

京东员工被裁后哀叹:优化后连面试的机会都没有,每月还要还贷款

Java 程序员 后端

为什么你不应该恨Java!

Java 程序员 后端

三年沉淀,Apache ShardingSphere 5.0.0 开启数据应用新篇章

SphereEx

Java 数据库 开源 Apache ShardingSphere DateBase

五分钟带你读懂!Spring Cloud构建微服务分布式云平台(1)

Java 程序员 后端

五分钟带你读懂!Spring Cloud构建微服务分布式云平台

Java 程序员 后端

京东T7团队技术4面:线程池+索引+Spring +分布式锁

Java 程序员 后端

京东T7架构师用470页就把微服务架构原理与开发实战文档讲完了(1)

Java 程序员 后端

小学妹与我畅聊黑客渗透技术

喀拉峻

黑客 网络安全 信息安全 渗透测试

事大发了!小助理告诉我:小伙伴21天斩获字节offer的关键竟是这份面试题!

Java 程序员 后端

云原生新边界——阿里云边缘计算云原生落地实践

Java 程序员 后端

五位阿里大牛联手撰写的《深入浅出Java多线程》,站在巨人的肩膀上学习!

Java 程序员 后端

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