版权声明:本文由张浩然原创文章,转载请注明出处: 
文章原文链接:https://www.qcloud.com/community/article/87

来源:腾云阁 https://www.qcloud.com/community

一.现状

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

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

1. 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. 新特性

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配合流量控制,可以实现很多很神奇的功能,这里卖个关子,然后会在下一篇讲解 :)

参考
HTTP/2之特性科普篇
《High Performance Browser Networking》——Ilya Grigorik;
《Web性能权威指南》-李松峰翻译;
Jerry Qu blog 中的HTTP/2专题;
HTTP/2.0 RFC7540
HTTP/2.0协议 中英对照——百度FEX

文章来源于公众号:小时光茶社(Tech Teahouse)

HTTP/2探索第一篇——概念的更多相关文章

  1. storm第一篇--概念,例子,参数优化

    1 概念 目前最新的0.8.0版本里面 worker -> 进程.一个worker只能执行同一个spout/bolt的task,一个worker里面可以有多个executor. executor ...

  2. python数据挖掘之数据探索第一篇

    目录 数据质量分析   当我们得到数据后,接下来就是要考虑样本数据集的数据和质量是否满足建模的要求?是否出现不想要的数据?能不能直接看出一些规律或趋势?每个因素之间的关系是什么?   通过检验数据集的 ...

  3. AntDesign-React与VUE有点不一样,第一篇深入了解React的概念之一:JSX

    AntDesign-React与VUE有点不一样,第一篇深入了解React的概念之一:JSX 一.什么是JSX 使用JSX声明一个变量(REACT当中的元素): const element =< ...

  4. vue-learning:40 - Vuex - 第一篇:概念和基本使用

    vuex 第一篇 目录 vuex概念 state / mapState getter / mapGetter mutation / mapMutation action / mapAction mod ...

  5. Flink入门-第一篇:Flink基础概念以及竞品对比

    Flink入门-第一篇:Flink基础概念以及竞品对比 Flink介绍 截止2021年10月Flink最新的稳定版本已经发展到1.14.0 Flink起源于一个名为Stratosphere的研究项目主 ...

  6. 第一篇 SQL Server安全概述

    本篇文章是SQL Server安全系列的第一篇,详细内容请参考原文. Relational databases are used in an amazing variety of applicatio ...

  7. [老老实实学WCF] 第一篇 Hello WCF

    老老实实学WCF  第一篇 Hello WCF WCF(Windows Communication Foundation)是微软公司推出的面向服务技术的集大成者,涵盖继承了其之前发布的所有的分布式应用 ...

  8. 老老实实学WCF[第一篇] Hell wcf

    老老实实学WCF  第一篇 Hello WCF WCF(Windows Communication Foundation)是微软公司推出的面向服务技术的集大成者,涵盖继承了其之前发布的所有的分布式应用 ...

  9. (转)[老老实实学WCF] 第一篇 Hello WCF

    http://blog.csdn.net/songyefei/article/details/7363296#comments 老老实实学WCF  第一篇 Hello WCF WCF(Windows ...

随机推荐

  1. CentOS下安装Gitlab

    环境 Requirements 软件 版本 CentOS 6.6 Python 2.6 Ruby 2.1.5 Git 1.7.10+ Redis 2.0+ MySQL   GitLab 7-8-sta ...

  2. 判断DataTable某字段是否包含某值

    // <summary> /// 判断DataTale中判断某个字段中包含某个数据 /// </summary> /// <param name="dt&quo ...

  3. Node.js获取mac网卡地址

    一.关于getmac node.js没有直接获取mac网卡地址的模块,此时我们需要借助于第三方模块getmac.getmac 可以帮助我们 获取当前机器上的mac地址.gatmac 下载地址为:htt ...

  4. 隐藏的Swiper显示后无法获取正确的宽度和高度

    今天在使用swiper的时候,元素默认是显示的时候没毛病,但是默认是隐藏的状态,再显示的时候发现滑动的时候宽度计算有误,如下图所示: 正确的显示如下: 隐藏的元素再次显示如下: 宽度计算有误 解决方案 ...

  5. 获取页面中更新删除传过来的id

    利用uri辅助函数 $id=$this->uri->segment(4); 其中segment(参数)  是表示你要截取获得第几个数据.

  6. 基于Dedup的数据打包技术

    基于Dedup的数据打包技术 0.引言    Tar, winrar, winzip是最为常见的数据打包工具软件,它们把文件集体封装成一个单独的数据包,从而方便数据的分布.传输.归档以及持久保存等目的 ...

  7. (转)MPEG4码流简单分析

    把MPEG4码流的分析和它的I,P,B Frame的判定方法在这里简要记录一下吧,供日后的翻看和大家的参考.   测试解码器测试了很久,由于需要将H264和MPEG4的码流进行分析和判断,并逐帧输入解 ...

  8. JBPM——工作流概念

    一.概念          工作流(Workflow),就是"业务过程的部分或总体在计算机应用环境下的自己主动化",它主要解决的是"使在多个參与者之间依照某种提前定义的规 ...

  9. HDU 1556 Color the ball 树状数组 题解

    Problem Description N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的"小飞鸽"牌电动 ...

  10. QTableWidget的表头颜色设置

    设置水平和垂直表头的颜色ui->tableWidget->horizontalHeader()->setStyleSheet("QHeaderView::section{b ...