HTTP

HTTP(HyperText Transger Protocol)

HTTP简介

超文本传输协议(英语:HyperText Transfer Protocol,缩写:HTTP)是一种用于分布式、协作式和超媒体信息系统的应用层协议。HTTP是万维网的数据通信的基础。

设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。通过HTTP或者HTTPS协议请求的资源由统一资源标识符(Uniform Resource Identifiers,URI)来标识。

HTTP的发展是由蒂姆·伯纳斯-李于1989年在欧洲核子研究组织(CERN)所发起。HTTP的标准制定由万维网协会(World Wide Web Consortium,W3C)和互联网工程任务组(Internet Engineering Task Force,IETF)进行协调,最终发布了一系列的RFC,其中最著名的是1999年6月公布的 RFC 2616,定义了HTTP协议中现今广泛使用的一个版本——HTTP 1.1。

传输or转移

关于HTTP中文翻译的讨论

为何HTTP被翻译为“超文本传输协议”是一次历史上的重大翻译错误?

李锟:

1.纸面释义

在IETF的RFC中,“transport”(传输)的含义是指:从端到端(例如从ip1:port1到ip2:port2)可靠地搬运比特,也就是TCP/IP协议栈中的第3层传输层(transport layer)协议所做的那些事情。

而“transfer”的含义是:通过在客户端-服务器端之间转移一些带有操作语义的操作原语,来执行某种操作。“transfer”是TCP/IP协议栈中的第4层应用层的概念,而不是第3层传输层的概念。“transfer”所转移的是带有明确操作语义的操作原语,而不是没有操作语义的比特流。

2.HTTP协议在TCP/IP协议族中的位置

HTTP其实是一种应用协议。HTTP/FTP/NNTP… 全是应用层协议。transfer是应用层的概念。传输这件事情,TCP+UDP已经干的很好了。

不过本着人有多大胆地有多大产的革命乐观冒险主义,非把HTTP当作传输协议来用,确实也死不了人。但是这是低效的用法,会付出一些代价。

3.HTTP设计者Fielding博士的释疑

HTTP定制者之一的Roy Fielding博士在其论文[1](6.5.3节)中使用“transfer”表达的是“(表述状态的)转移”(Representational State Transfer),而不是“传输”。这是因为英语单词“transfer”在不同语境下的多义性,请勿误解。

6.5.3 HTTP is not a Transport Protocol

HTTP is not designed to be a transport protocol. It is a transfer protocol in which the messages reflect the semantics of the Web architecture by performing actions on resources through the transfer and manipulation of representations of those resources. It is possible to achieve a wide range of functionality using this very simple interface, but following the interface is required in order for HTTP semantics to remain visible to intermediaries.

HTTP不是为了设计成一个传输协议。它是一个转移协议,通过对资源表征的转移和操作,它反映了Web架构的含义。它使得通过简单的接口实现非常大范围的功能诉求,同时接口又是必须的,它使得HTTP的语义对于中间媒介保持可见。

4.HTTP协议的有设计与发展

HTTP协议为何要这样设计、设计出来是为了做什么事情,指导思想是REST。REST其实就是中庸之道,没什么神秘。

HTTP 1.0和HTTP 1.1最大的区别是什么,我接下来详细解释。

HTTP 1.0基本上就是一个服务器端静态文件的操作协议,并没有抽象的资源概念,HTTP 1.0认为Web服务器上就是一大堆静态文件。HTTP 1.0里面的transfer,就是传递、转移文件。有人把它理解为传输,似乎也可以。但是在协议里面,传输transport其实指的是搬运bit层次的苦力活。

如何来很好地支持动态内容,是HTTP 1.1协议要解决的一个主要问题。因此就发明了一个新的概念叫做资源,注意:资源和面向对象编程里面的对象类似,是一个抽象的工具。资源不仅仅可以代表服务器端一个文件、数据库中一条记录这类具体的东西。可以要多抽象有多抽象。有了资源之后,还需要设计一个统一的接口来操作资源。否则每一个资源操作的方式都不一样,那样做会严重降低Web应用的可伸缩性。

陈睿杰-小狗

其实说起来,http还真和邮局很相似,你去寄信,信封上的东西,比如地址、邮编,是有语义的,你可以看作是“应用层”的东西,你通过信件“转移”你的想法给对方;邮局的派送车,只管帮你运输的,那个是“传输层”的东西,帮你“传输”这封信件。
  对应到HTTP协议的内容,request header、response header,就是信封上的元信息,body是你的信件内容。http很依赖这些元信息的,它根本不关注整个东西是怎么送达到对方手里的,传输有TCP、IP在做了。

其实要真正明白区别,就要明白资源的概念,资源是抽象的概念,你不可能在网络上真正的交换一个资源实体,你只能操作表述,资源永远无法直接触及,在REST架构中,服务器和客户端之间都只能通过资源的表述来进行交流,而非资源本身,这就是为什么要用“转移”来称呼这个操作。转移表述,而非传输资源。

一次完整的HTTP请求经历的所有环节

就拿https://www.baidu.com/为例,以下对一次完整的HTTP请求经历的所有环节进行了详细的讲解:

  1. chrome搜索自身的dns缓存,如果有,看缓存是否过期?如果过期或没有则缓存结束;
  2. 搜索操作系统自身的DNS缓存(浏览器没有找到缓存或缓存已失效);
  3. 读取本地的HOST文件;
  4. 浏览器发起 个DNS的一个系统调 ;
  • 4.1 宽带运营商服务器查看本身缓存;
  • 4.2 运营商DNS服务器代替浏览 发起一个迭代DNS解析的请求;
    先找到根域的DNS的IP地址;得到顶级域com域的IP地址;
    向com域的DNS服务 查询,得到baidu.com这个域的IP地址;(域名注册商提供,如:万网,新网等);
    从baidu.com这个域的DNS服务 得到我们的域名对应的ip地址;
    运营服务商把结果返回给操作系统内核,同时缓存起来;操作系统内核把结果返回浏览 ;最终浏览器拿到 www.baidu.com (http://www.baidu.com) 对应的ip地址域名解析完成后;
  1. 浏览器获得域名对应的ip地址后,发起TCP“三次握手”;
    TCP连接请求:该请求通过层层路由设备到达服务器端以后,进入到网卡,然后进入到内盒的TCP/IP协议栈,再通过防火墙的过滤,最终到达web的服务端;建 TCP和IP的链接;

  2. TCP/IP 连接建立起来后,浏览器就可以向服务器发送HTTP请求 ,使用了比如说,用HTTP的GET 法请求一个根域里的一个域名;

  3. 服务器端接收到请求,根据路径参数,经过后台的一些处理之后,把处理后的结果数据返回给浏览器,比如百度的HTML页面代码返回给浏览器;

  4. 浏览器拿到HTML页面代码,在解析和渲染这个页面的时候,里面的JS,CSS,图片静态资源,它们也同样是一个个HTTP请求,需要经历1-7的步骤;

  5. 浏览器根据拿到的资源,对页面进行渲染

在一个HTTP请求中使用了那些重要的协议?

物理层

数据链路层

网络层:IP

传输层:TCP

应用层:DNS

URI 和 URL

URI = Uniform Resource Identifier统一资源标志符
URL = Uniform Resource Locator统一资源定位符

RFC2396下的URI定义:

Uniform

规定统一的格式可方便处理多种不同类型的资源,而不用根据上下文环境来识别资源指定的访问方式。另外,加入加入新增的协议方案(如http:或ftp:)也更容易

Resource

资源的定义是“可标识的任何东西”。不仅是文档文件,图片或服务(例如当天的天气预报)等能够区别与其他类型的,全都可作为资源。另外,资源不仅可以单一的,也可以是多数的集合体。

Identifier

表示可标识的对象。也称为标识符

URL

URL在于Locater,一般来说(URL)统一资源定位符,可以提供找到该资源的路径。也是一种URI,即URI包含URL

URL由三部分组成:资源类型、存放资源的主机域名、资源文件名。

URL的一般语法格式为:

(带方括号[]的为可选项):

protocol / hostname[:port] / path / [;parameters][?query]#fragment

//"http://localhost:8888/bb?name=bigbear&memo-helloworld"
Url {
  protocol: 'http:',
  slashes: true,
  auth: null,
  host: 'localhost:8888',
  port: '8888',
  hostname: 'localhost',
  hash: null,
  search: '?name=bigbear&memo-helloworld',
  query: 'name=bigbear&memo-helloworld',
  pathname: '/bb',
  path: '/bb?name=bigbear&memo-helloworld',
  href: 'http://localhost:8888/bb?name=bigbear&memo-helloworld' 
}
URL和URI的区别

统一资源标志符URI就是在某一规则下能把一个资源独一无二地标识出来。
拿人做例子,假设这个世界上所有人的名字都不能重复,那么名字就是URI的一个实例,通过名字这个字符串就可以标识出唯一的一个人。
现实当中名字当然是会重复的,所以身份证号才是URI,通过身份证号能让我们能且仅能确定一个人。
那统一资源定位符URL是什么呢。也拿人做例子然后跟HTTP的URL做类比,就可以有:

动物住址协议://地球/中国/浙江省/杭州市/西湖区/某大学/14号宿舍楼/525号寝/张三.人

可以看到,这个字符串同样标识出了唯一的一个人,起到了URI的作用,所以URL是URI的子集。URL是以描述人的位置来唯一确定一个人的。
在上文我们用身份证号也可以唯一确定一个人。对于这个在杭州的张三,我们也可以用:

身份证号:123456789

来标识他。
所以不论是用定位的方式还是用编号的方式,我们都可以唯一确定一个人,都是URl的一种实现,而URL就是用定位的方式实现的URI。

回到Web上,假设所有的Html文档都有唯一的编号,记作html:xxxxx,xxxxx是一串数字,即Html文档的身份证号码,这个能唯一标识一个Html文档,那么这个号码就是一个URI。

而URL则通过描述是哪个主机上哪个路径上的文件来唯一确定一个资源,也就是定位的方式来实现的URI。

HTTP 报文结构

HTTP 报文有 请求报文响应报文 两种。
请求报文:从客户向服务器发送请求报文。
响应报文:从服务端到客户的回答。

HTTP的这两种报文都由三部分组成:开始行首部行实体主体

开始行

请求报文的开始行

也叫请求行,由 方法[空格]URL[空格]HTTP版本 组成。

例:

GET /helloworld HTTP/1.1

方法: 向请求资源指定的资源发送请求报文的方法,其作用是可以指定请求的资源按期望产生某种行为。
URL : 链接

响应报文的开始行

也叫响应行,由 HTTP 版本[空格]状态码[空格]状态码的原因短语组成。

**状态码(Status-Code)**都是三位数字的,分为 5 大类共 33 种。
如:

状态码 说明 请求行例子
1xx 表示通知信息的,如请求收到了或正在进行处理
2xx 表示成功 HTTP/1.1 200 OK
3xx 表示重定向
4xx 表示客户端的差错,如请求链接为不存在 HTTP/1.1 404 Not Found
5xx 表示服务器的差错

首部行

1.是用来说明浏览器、服务器或报文主体的一些信息。
2.可以有好几行,也可以不使用
3.每个首部行都是由 首部字段名[空格] 组成
4.每个首部行在结束地方都有 CRLF(『回车』和『换行』符)

HTTP 首部字段分为 4 种: 通用首部字段请求首部字段响应首部字段实体首部字段

实体主体

在请求报文中,一般是 post/put 提交的表单信息。与首部行之间有 CRLF 即空行。

HTTP 请求方法

GET

GET 是最常用的方法。

GET方法用来请求访问已被URI识别的资源。指定的资源经服务端解析后返回响应内容。如果请求的资源为文本,那就保持原样返回:如果想CGI(Common Gateway Interface,通用网关接口)那样的程序,则返回已经执行后的输出结果。

HEAD

HEAD 方法与 GET 方法的行为很类似,但服务器在响应中只返回首部。不会返回实体的主体部分。这就允许客户端在未获取实际资源的情况下,对资源的首部进行检查。使用 HEAD,可以:

  • 在不获取资源的情况下了解资源的情况(比如,判断其类型);
  • 通过查看响应中的状态码,看看某个对象是否存在;
  • 通过查看首部,测试资源是否被修改了。

服务器开发者必须确保返回的首部与 GET 请求所返回的首部完全相同。

PUT

与 GET 从服务器读取文档相反,PUT 方法会向服务器写入文档。有些发布系统允许用户创建 Web 页面,并用 PUT 直接将其安装到 Web 服务器上去。

PUT 方法的语义就是让服务器用请求的主体部分来创建一个由所请求的 URL 命名的新文档,或者,如果那个 URL 已经存在的话,就用这个主体来替代它。

因为 PUT 允许用户对内容进行修改,所以很多 Web 服务器都要求在执行 PUT 之前,用密码登录。

POST

POST 方法起初是用来向服务器输入数据(传输实体主体)的。实际上,通常会用它来支持 HTML 的表单。表单中填好的数据通常会被送给服务器,然后由服务器将其发送到它要去的地方(比如,送到一个服务器网关程序中,然后由这个程序对其进行处理)。

注: POST 用于向服务器发送数据。PUT 用于向服务器上的资源(例如文件)中存储数据。

TRACE

客户端发起一个请求时,这个请求可能要穿过防火墙、代理、网关或其他一些应用程序。每个中间节点都可能会修改原始的 HTTP 请求。TRACE 方法允许客户端在 最终将请求发送给服务器时,看看它变成了什么样子。

TRACE 请求会在目的服务器端发起一个 环回 诊断。行程最后一站的服务器会弹回一条 TRACE 响应,并在响应主体中携带它收到的原始请求报文。这样客户端就可以查看在所有中间 HTTP 应用程序组成的请求 / 响应链上,原始报文是否,以及如何被毁坏或修改过。

HTTP_第1张图片

TRACE 方法主要用于诊断;也就是说,用于验证请求是否如愿穿过了请求 / 响应链。它也是一种很好的工具,可以用来查看代理和其他应用程序对用户请求所产生 效果。

OPTIONS

OPTIONS 方法请求 Web 服务器告知其支持的各种功能。可以询问服务器通常支持哪些方法,或者对某些特殊资源支持哪些方法。(有些服务器可能只支持对一些特殊类型的对象使用特定的操作)。

通过使用 OPTIONS,客户端可以在与服务器进行交互之前,确定服务器的能力,这样它就可以更方便地与具备不同特性的代理和服务器进行互操作了。

这为客户端应用程序提供了一种手段,使其不用实际访问那些资源就能判定访问各种资源的最优方式。

HTTP_第2张图片

如果 OPTIONS 请求的 URI 是个星号(*),请求的就是整个服务器所支持的功能。

比如:

OPTIONS * HTTP/1.1

如果 URI 是个实际资源地址,OPTIONS 请求就是在查询那个特定资源的可用特性:

OPTIONS http://www.joes-hardware.com/index.html HTTP/1.1

如果成功,OPTIONS方法就会返回一个包含了各种首部字段的200 OK响应,这些 字段描述了服务器所支持的,或资源可用的各种可选特性。HTTP/1.1 在响应中唯一 指定的首部字段是 Allow 首部,这个首部用于描述服务器所支持的各种方法(或者 服务器上的特定资源)。OPTIONS 允许在可选的响应主体中包含更多的信息,但并没有对这种用法进行定义。

DELETE

顾名思义,DELETE 方法所做的事情就是请服务器删除请求 URL 所指定的资源。 但是,客户端应用程序无法保证删除操作一定会被执行。因为 HTTP 规范允许服务 器在不通知客户端的情况下撤销请求。

HTTP_第3张图片

CONNECT

CONNECT方法是HTTP/1.1协议预留的,能够将连接改为管道方式的代理服务器。通常用于SSL加密服务器的链接与非加密的HTTP代理服务器的通信。

PATCH

PATCH方法出现的较晚,它在2010年的 RFC 5789 PATCH Method for HTTP 标准中被定义。PATCH请求与PUT请求类似,同样用于资源的更新。二者有以下两点不同:

  • 但PATCH一般用于资源的部分更新,而PUT一般用于资源的整体更新。
  • 当资源不存在时,PATCH会创建一个新的资源,而PUT只会对已在资源进行更新。

HTTP版本

大致版本可以分为以下四个:

  • HTTP/0.9
  • HTTP/1.0
  • HTTP/1.1
  • HTTP/2

发展的历史如下:

HTTP_第4张图片

HTTP/0.9

HTTP 是基于 TCP/IP 协议的应用层协议。它不涉及数据包(packet)传输,主要规定了客户端和服务器之间的通信格式,默认使用 80 端口。 最早版本是 1991 年发布的 0.9 版。该版本极其简单,只有一个命令 GET。

GET /index.html

上面命令表示,TCP 连接(connection)建立后,客户端向服务器请求(request)网页 index.html。协议规定,服务器只能回应 HTML 格式的字符串,不能回应别的格式。


  Hello World

服务器发送完毕,就关闭 TCP 连接。

HTTP/1.0

1996 年 5 月,HTTP/1.0 版本发布,内容大大增加。 相对于 HTTP/0.9 大致增加了如下几点:

  • 首先,任何格式的内容都可以发送。这使得互联网不仅可以传输文字,还能传输图像、视频、二进制文件。这为互联网的大发展奠定了基础
  • 其次,除了 GET 命令,还引入了 POST 命令和 HEAD 命令,丰富了浏览器与服务器的互动手段
  • 再次,HTTP 请求和回应的格式也变了。除了数据部分,每次通信都必须包括头信息(HTTP header),用来描述一些元数据
  • 其他的新增功能还包括状态码**(status code)、多字符集支持、多部分发送(multi-part type)、权限(authorization)、缓存(cache)、内容编码(content encoding)**等。

当时其实也存在一些别的问题如下:

  • HTTP/1.0 版的主要缺点是,每个 TCP 连接只能发送一个请求。发送数据完毕,连接就关闭,如果还要请求其他资源,就必须再新建一个连接。
  • TCP 连接的新建成本很高,因为需要客户端和服务器三次握手,并且开始时发送速率较慢(slow start)

HTTP/1.1

1997 年 1 月,HTTP/1.1 版本发布,只比 1.0 版本晚了半年。它进一步完善了 HTTP 协议,一直用到了 20 年后的今天,直到现在还是最流行的版本。

相对于 HTTP/1.0 版本 HTTP/1.1 做了一些优化大致如下:

  • 长连接: HTTP 1.1 支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个 TCP 连接上可以传送多个 HTTP 请求和响应,减少了建立和关闭连接的消耗和延迟,在 HTTP1.1 中默认开启 Connection: keep-alive,一定程度上弥补了 HTTP1.0 每次请求都要创建连接的缺点。
  • **缓存处理:**在 HTTP1.0 中主要使用 header 里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1 则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。
  • 带宽优化及网络连接的使用,HTTP1.0 中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1 则在请求头引入了range 头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。
  • 错误通知的管理,在 HTTP1.1 中新增了24 个错误状态响应码,如 409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
  • Host 头处理,在 HTTP1.0 中认为每台服务器都绑定一个唯一的 IP 地址,因此,请求消息中的 URL 并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个 IP 地址。HTTP1.1 的请求消息和响应消息都应支持 Host 头域,且请求消息中如果没有 Host 头域会报告一个错误(400 Bad Request)。

但是同时也存在一些问题如下:

  • 虽然 1.1 版允许复用 TCP 连接,但是同一个 TCP 连接里面,所有的数据通信是按次序进行的。服务器只有处理完一个回应,才会进行下一个回应。要是前面的回应特别慢,后面就会有许多请求排队等着。这称为"队头堵塞"(Head-of-line blocking)
  • HTTP1.x 在传输数据时,所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份,这在一定程度上无法保证数据的安全性。
  • HTTP1.x 在使用时,header 里携带的内容过大,在一定程度上增加了传输的成本,并且每次请求 header 基本不怎么变化,尤其在移动端增加用户流量。
  • 虽然 HTTP1.x 支持了 keep-alive,来弥补多次创建连接产生的延迟,但是 keep-alive 使用多了同样会给服务端带来大量的性能压力,并且对于单个文件被不断请求的服务(例如图片存放网站),keep-alive 可能会极大的影响性能,因为它在文件被请求之后还保持了不必要的连接很长时间。

SPDY 协议

2009 年,谷歌公开了自行研发的 SPDY 协议,主要解决 HTTP/1.1 效率不高的问题。 这个协议在 Chrome 浏览器上证明可行以后,就被当作 HTTP/2 的基础,主要特性都在 HTTP/2 之中得到继承。SPDY 可以说是综合了 HTTPS 和 HTTP 两者有点于一体的传输协议,主要解决:

  • 降低延迟,针对 HTTP 高延迟的问题,SPDY 优雅的采取了多路复用(multiplexing)。多路复用通过多个请求 stream 共享一个 tcp 连接的方式,解决了 HOL blocking 的问题,降低了延迟同时提高了带宽的利用率。
  • 请求优先级(request prioritization)。多路复用带来一个新的问题是,在连接共享的基础之上有可能会导致关键请求被阻塞。SPDY 允许给每个 request 设置优先级,这样重要的请求就会优先得到响应。比如浏览器加载首页,首页的 html 内容应该优先展示,之后才是各种静态资源文件,脚本文件等加载,这样可以保证用户能第一时间看到网页内容。
  • header 压缩。前面提到 HTTP1.x 的 header 很多时候都是重复多余的。选择合适的压缩算法可以减小包的大小和数量。
  • 基于 HTTPS 的加密协议传输,大大提高了传输数据的可靠性
  • 服务端推送(server push),采用了 SPDY 的网页,例如我的网页有一个 sytle.css 的请求,在客户端收到 sytle.css 数据的同时,服务端会将 sytle.js 的文件推送给客户端,当客户端再次尝试获取 sytle.js 时就可以直接从缓存中获取到,不用再发请求了。

SPDY 构成图:

HTTP_第5张图片

HTTP/2

HTTP/2 可以说是 SPDY 的升级版(其实原本也是基于 SPDY 设计的),但是,HTTP2.0 跟 SPDY 仍有不同的地方,主要是以下两点:

  • HTTP2.0 支持明文 HTTP 传输,而 SPDY 强制使用 HTTPS
  • HTTP2.0 消息头的压缩算法采用 HPACK,而非 SPDY 采用的 DEFLATE

HTTP/2 的新特性:

  • 二进制分帧:HTTP/2 的所有帧都采用二进制编码
  • 多路复用 (Multiplexing)
  • 请求优先级
  • header 压缩
  • 服务端推送

二进制分帧:

HTTP/2 的所有帧都采用二进制编码

先理解几个概念:

  • :客户端与服务器通过交换帧来通信,帧是基于这个新协议通信的最小单位。
  • 消息:是指逻辑上的 HTTP 消息,比如请求、响应等,由一或多个帧组成。
  • :流是连接中的一个虚拟信道,可以承载双向的消息;每个流都有一个唯一的整数标识符(1、2…N);

HTTP/2 采用二进制格式传输数据,而非 HTTP 1.x 的文本格式,二进制协议解析起来更高效。 HTTP / 1 的请求和响应报文,都是由起始行,首部和实体正文(可选)组成,各部分之间以文本换行符分隔。HTTP/2 将请求和响应数据分割为更小的帧,并且它们采用二进制编码。

HTTP_第6张图片

帧、流、消息的关系

每个数据流都以消息的形式发送,而消息又由一个或多个帧组成帧是流中的数据单位。一个数据报的 header 可以分成多个 header 帧,data 可以分成多个 data 帧。

多路复用 (Multiplexing)

多路复用允许同时通过单一的 HTTP/2 连接发起多重的请求-响应消息。即连接共享,即每一个 request 都是是用作连接共享机制的。一个 request 对应一个 id,这样一个连接上可以有多个 request,每个连接的 request 可以随机的混杂在一起,接收方可以根据 request 的 id 将 request 再归属到各自不同的服务端请求里面。 多路复用原理图:

HTTP_第7张图片

请求优先级

  • 把 HTTP 消息分解为很多独立的帧之后,就可以通过优化这些帧的交错和传输顺序,每个流都可以带有一个 31 比特的优先值:0 表示最高优先级;2 的 31 次方-1 表示最低优先级。
  • 服务器可以根据流的优先级,控制资源分配(CPU、内存、带宽),而在响应数据准备好之后,优先将最高优先级的帧发送给客户端。
  • HTTP 2.0 一举解决了所有这些低效的问题:浏览器可以在发现资源时立即分派请求,指定每个流的优先级,让服务器决定最优的响应次序。这样请求就不必排队了,既节省了时间,也最大限度地利用了每个连接。

header 压缩

HTTP1.x 的 header 带有大量信息,而且每次都要重复发送,HTTP/2 使用 encoder 来减少需要传输的 header 大小,通讯双方各自cache 一份 header fields 表,既避免了重复 header 的传输,又减小了需要传输的大小。 为了减少这块的资源消耗并提升性能, HTTP/2 对这些首部采取了压缩策略:

  • HTTP/2 在客户端和服务器端使用“首部表”来跟踪和存储之前发送的键-值对,不再重复发送 header
  • 首部表在 HTTP/2 的连接存续期内始终存在,由客户端和服务器共同渐进地更新;
  • 每个新的首部键-值对要么被追加到当前表的末尾,要么替换表中之前的值

两次请求不相同的 header,传说的 header 如下图所示:

HTTP_第8张图片

服务端推送

Server Push 即服务端能通过 push 的方式将客户端需要的内容预先推送过去,也叫“cache push”。 服务器可以对一个客户端请求发送多个响应。服务器向客户端推送资源无需客户端明确地请求,服务端可以提前给客户端推送必要的资源,这样可以减少请求延迟时间,例如服务端可以主动把 JS 和 CSS 文件推送给客户端,而不是等到 HTML 解析到资源时发送请求,大致过程如下图所示:

HTTP_第9张图片

注意: 所有推送的资源都遵守同源策略服务器必须遵循请求- 响应的循环,只能借着对请求的响应推送资源

总结

从 http/0.9 到 http/2 的发展,有了很多的优化点如下:

  • 二进制分帧:HTTP/2 的所有帧都采用二进制编码
  • 多路复用 (Multiplexing)
  • 请求优先级
  • header 压缩
  • 服务端推送

你可能感兴趣的:(HTTP,http)