超文本传输协议(HTTP)是万维网的基础,用于通过超文本链接加载网页。HTTP是应用层协议的一种,旨在在联网设备之间传输信息,并在网络协议堆栈的其他层之上运行。HTTP是基于TCP / IP的通信协议,默认端口是TCP 80,但也可以使用其他端口。
HTTP 协议基本特性:
HTTP 会话由 HTTP 客户端(即用户的浏览器)通过用户代理打开,并且连接请求消息被发送到 HTTP 服务器(即Web服务器)。请求消息也称为“客户端请求”,由以下几行组成:
传递响应后,Web 服务器将关闭连接。这种连接称为无状态连接,因为它仅在数据交换期间存在。
请求行
请求行以一个方法符号开头,以空格分开,后面跟着请求的URI和协议的版本,格式如下:
Method Request-URI HTTP-Version CRLF
Method
表示请求方法;
Request-URI
是一个统一资源标识符;
HTTP-Version
表示请求的 HTTP 协议版本;
CRLF
表示回车和换行(除了作为结尾的 CRLF
外,不允许出现单独的 CR
或 LF
字符)。
请求方法(所有方法全为大写)有多种,各个方法的解释如下:
GET : 请求获取Request-URI所标识的资源
POST :在Request-URI所标识的资源后附加新的数据
HEAD :请求获取由Request-URI所标识的资源的响应消息报头
PUT : 请求服务器存储一个资源,并用Request-URI作为其标识
DELETE :请求服务器删除Request-URI所标识的资源
TRACE :请求服务器回送收到的请求信息,主要用于测试或诊断
CONNECT:保留将来使用
OPTIONS :请求查询服务器的性能,或者查询与资源相关的选项和需求
请求头
HTTP 消息报头包括:普通报头、请求报头、响应报头、实体报头,每一个报头域都是由名字 + : + 空格 + 值
组成,消息报头域的名字是大小写无关的。
普通报头
在普通报头中,有少数报头域用于所有的请求和响应消息,但并不用于被传输的实体,只用于传输的消息。
字段名 | 说明 |
---|---|
Cache-Control | 控制缓存行为 |
Connection | 连接的管理 |
Date | 普通报头域表示消息产生的日期和时间 |
Pragma | http 1.0 中的保温指令控制 |
请求报头
请求报头允许客户端向服务器端传递请求的附加信息以及客户端自身的信息。常见的请求报头包括:
字段名 | 说明 |
---|---|
Accept | 客户端可处理的媒体类型:Accept:image/gif |
Accept-Charset | 客户端可处理的字符集 |
Accept-Encoding | 客户端的编码方式 |
Accept-Langulage | 客户端指定的语言类型 |
Authrization | web认证信息 |
Expect | 期待服务器的特定行为 |
Host | 请求报头域主要用于指定被请求资源的 Internet 主机和端口号 |
User-Agent | 请求报头域允许客户端将它的操作系统、浏览器和其它属性 |
Referer | 请求中的 url 上一跳地址 |
响应报头
响应报头允许服务器传递不能放在状态行中的附加响应信息,以及关于服务器的信息和对Request-URI所标识的资源进行下一步访问的信息。常见的响应报头包括:
字段名 | 说明 |
---|---|
Age | 资源的创建时间 |
Location | 客户端重定向至指定的URL |
Retry-After | 再次发送请求的时机 |
www-Authenticate | 服务器对客户端的认证 |
实体报头
请求和响应消息都可以传送一个实体。一个实体由实体报头域和实体正文组成,但并不是说实体报头域和实体正文要在一起发送,可以只发送实体报头域。实体报头定义了关于实体正文和请求所标识的资源的元信息。
字段名 | 说明 |
---|---|
Allow | 资源所支持的HTTP请求类型 |
Content-Encoding | 数据编码方式 |
Content-Language | 数据的语言类型 |
Content-Length | 实体的内容大小 |
Content-Location | 替代对应资源的URI |
Content-Type | 实体报头域用语指明发送给接收者的实体正文的媒体类型 |
Expires | 数据过期时间 |
Last-Modified | 资源的最后修改时间 |
状态码用于告知请求方当次请求的状态是成功还是失败,常见的状态码有以下分类:
类别 | 说明 |
---|---|
1XX | Informational(信息性状态码) |
2XX | Success(成功状态码) |
3XX | Redirection(重定向) |
4XX | Client Error(客户端错误状态码) |
5XX | Server Error(服务器错误状态码) |
2XX 成功
3XX 重定向
300 :Multiple Choices 客户请求的文档可以在多个位置找到,这些位置已经在返回的文档内列出。如果服务器要提出优先选择,则应该在 Location 应答头指明。
301 :Moved Permanently 客户请求的文档在其他地方,新的 URL 在 Location 头中给出,浏览器应该自动地访问新的 URL。
302 :Found 类似于 301,但新的 URL 应该被视为临时性的替代,而不是永久性的。注意,在 HTTP1.0 中对应的状态信息是“Moved Temporatily”。
出现该状态代码时,浏览器能够自动访问新的 URL,因此它是一个很有用的状态代码。
注意这个状态代码有时候可以和301替换使用。例如,如果浏览器错误地请求 http://host/~aaa
(缺少了后面的斜杠),有的服务器返回301,有的则返回302。
严格地说,我们只能假定只有当原来的请求是 GET 时浏览器才会自动重定向。请参见 307。
303 :See Other 类似于 301 / 302,不同之处在于,如果原来的请求是 POST,Location 头指定的重定向目标文档应该通过GET提取(HTTP 1.1新)。
304 :Not Modified 客户端有缓冲的文档并发出了一个条件性的请求(一般是提供 If-Modified-Since
头表示客户只想比指定日期更新的文档)。服务器告诉客户,原来缓冲的文档还可以继续使用。
305 :Use Proxy 客户请求的文档应该通过 Location 头所指明的代理服务器提取(HTTP /1.1新)。
307 :Temporary Redirect 和 302(Found)相同。许多浏览器会错误地响应 302 应答进行重定向,即使原来的请求是 POST,即使它实际上只能在 POST 请求的应答是 303 时才能重定向。由于这个原因,HTTP/1.1 新增了 307,以便更加清楚地区分几个状态代码:当出现 303 应答时,浏览器可以跟随重定向的 GET 和 POST 请求;如果是 307 应答,则浏览器只能跟随对 GET 请求的重定向。(HTTP/ 1.1新)
4XX 客户端错误
WWW-Authenticate
头,浏览器据此显示用户名字/密码对话框,然后在填写合适的 Authorization 头后再次发出请求。5XX 服务器端错误
HTTP 最早诞生的版本是 0.9,于1991年提出。最早的需求很简单主要是在两个网络之间传输 HTML 内容,所以被称为超文本传输协议。
早期的互联网也非常的简单,常见的都是静态页面。所以刷互联网基本都是一些 BBS 帖子之类的。HTTP/0.9 的实现有 3 个特点:
到了 1994 年之后,网络发展的速度超出大家的预估,简单的 HTML 不再能满足日益增长的互联网用户需求,动态交互的需求使得新的交互协议出现进而促进了浏览器领域的变革,图片,音频,文件传输,动态渲染等等我们今天看起来很平常的功能在当时是非常炫酷的东西。那么之前的 0.9 版本协议必然不能满足当前需求,所以新的版本最核心的需求就是支持多协议,多编码。
HTTP/1.0 的特性如下:
基于上面 1.0 的缺点,亟待解决的问题有:
所以在 1.1 版本做了如下优化:
Keep-Alive
可以保持 HTTP 连接不断开,避免了每次客户端与服务器请求都要重复建立释放建立TCP连接,提高了网络的利用率。如果客户端想关闭 HTTP 连接,可以在请求头中携带 Connection: false
来告知服务器关闭请求。keep-alive
就起了很大的作用,能够进行“并行”发送多个请求。这里要说的是,HTTP/1.1 管道化所谓的并行传输其实并未做到真正的并行。服务器必须按照客户端请求的先后顺序依次回送相应的结果,以保证客户端能够区分出每次请求的响应内容。即管道化做的事情是把先进先出的队列从客户端迁移到了服务器,由服务器来维护这个状态。
但是在服务器的响应是有先后顺序的。比如:
客户端同时发送两个请求:
这时候在服务器是 css 资源先准备好,但是服务器还是会等 html 资源准备好先发送 html 资源,等响应完毕再发送css资源。可见所谓的管道化技术还是无法解决 “阻塞” 的问题。同时,因为管道化技术存在各种各种的问题,浏览器厂商要么直接关闭该功能,要么就直接不支持,所以实际上该功能并没有被用到。
目前浏览器厂商采用的做法是针对同一个域名,最多允许同时发起6个请求,所以通过这种方式真正的做到了并行。
HTTP 协议的早期版本是专门为简化实现而设计的:
HTTP / 0.9 是用于引导万维网的单行协议;
HTTP / 1.0 在信息标准中记录了对 HTTP / 0.9 的流行扩展;
HTTP / 1.1 引入了正式的 IETF 标准。
不幸的是,HTTP / 1.x 实现简单性也以牺牲应用程序性能为代价:
客户端需要使用多个连接来实现并发和减少延迟;
不会压缩请求和响应头,从而导致不必要的网络流量;
不允许有效的资源优先级划分,从而导致底层 TCP 连接的使用不充分。
这些限制并不是致命的,但是随着 Web 应用程序的范围,复杂性和在日常生活中的重要性不断增长,它们给 Web 开发人员和用户带来了越来越大的负担,这正是 HTTP / 2旨在解决:
HTTP / 2 对 HTTP / 1.1 的主要更改集中在提高性能上:诸如多路复用,标头压缩,优先级划分和协议协商之类的一些关键功能。
二进制框架
HTTP / 2 所有性能增强的核心是新的二进制框架层,该层指示如何在客户端和服务器之间封装和传输HTTP消息。
新的二进制框架旨在对请求体内容做进一步编码以使得传输更为高效,HTTP语义(请求头,请求行)不受影响,但是它们的方式在运输过程中的编码是不同的。与换行符分隔的纯文本HTTP / 1.x协议不同,所有HTTP / 2通信都分为较小的消息和帧,每个消息和帧均以二进制格式编码。主要有以下概念:
流,消息和帧
新的二进制框架机制的引入改变了客户端和服务器之间数据交换的方式。为了描述这个过程,让我们熟悉一下HTTP / 2术语:
这些术语的关系可以概括如下:
简而言之,HTTP / 2 将 HTTP 协议通信分解为交换二进制编码的帧,然后将其映射到属于特定流的消息,所有这些消息都在单个 TCP 连接中进行多路复用。这是启用 HTTP / 2 协议提供的所有其他功能和性能优化的基础。
请求和响应多路复用
使用 HTTP / 1.x,如果客户端希望发出多个并行请求以提高性能,则必须使用多个 TCP 连接。此行为是HTTP / 1.x 传递模型的直接结果,该模型确保每个连接一次只能传递一个响应(响应队列)。更糟糕的是这还会导致行头阻塞和底层 TCP 连接的低效使用。
HTTP / 2中新的二进制框架层消除了这些限制,并通过允许客户端和服务器将 HTTP 消息分解为独立的帧,进行交织,然后在另一端重新组装,从而实现了完整的请求和响应多路复用。
快照捕获同一连接中正在运行的多个流。客户端正在DATA
向服务器传输帧(流5),而服务器正在向客户端传输流 1 和 3 的帧的交错序列。结果,正在运行三个并行流。
将 HTTP 消息分解为独立的帧,进行交织,然后在另一端重新组装的能力,是HTTP / 2 的最重要的增强。实际上,它在所有 Web 技术的整个堆栈中引入了许多性能优势的连锁反应,使我们能够:
HTTP / 2 中新的二进制框架层解决了 HTTP / 1.x 中出现的行头阻塞问题,并且消除了对多个连接的需要,以实现请求和响应的并行处理以及传递。
流优先级
一旦 HTTP 消息可以分为多个单独的帧,并且我们允许将来自多个流的帧进行多路复用,则客户端和服务器对帧进行交错和传递的顺序就成为了关键的性能考量。为方便起见,HTTP / 2 标准允许每个流具有关联的权重和依赖性:
流依赖性和权重的组合使客户端可以构建和传达“优先级树”,该树表示希望接收响应的方式。反过来,服务器可以使用此信息通过控制 CPU,内存和其他资源的分配来优先处理流,并且一旦响应数据可用,就可以分配带宽以确保将高优先级响应最佳地交付给客户端。
通过将另一个流的唯一标识符引用为其父级来声明 HTTP / 2 中的流依赖性。如果省略标识符,则称该流依赖于“根流”。声明流依赖关系表示,如果可能,应在父流之前为其资源分配资源。换句话说,“请在响应 C 之前处理并交付响应 D ”。
共享同一父级的流(换句话说,同级流)应按其权重分配资源。例如,如果流A的权重为12,而其同级B的权重为4,则确定每个流应接收的资源比例:
4 + 12 = 16
A = 12/16, B = 4/16
因此,流 A 应该获得四分之三,流B应该获得四分之一的可用资源。流 B 应该收到分配给流A的资源的三分之一。让我们通过上图中的一些动手示例进行研究。从左到右:
如以上示例所示,流依赖性和权重的组合提供了一种表达资源优先级的语言,这是提高浏览性能的关键功能,因为我们拥有许多具有不同依赖性和权重的资源类型。更好的是,HTTP / 2 协议还允许客户端在任何时候更新这些首选项,从而可以在浏览器中进行进一步的优化。换句话说,我们可以更改依赖关系并根据用户交互和其他信号重新分配权重。
每个来源一个连接
有了新的二进制帧机制,HTTP / 2 不再需要多个 TCP 连接来并行多路复用流。每个流都分为许多帧,可以进行交织并确定优先级。结果,所有HTTP / 2连接都是持久的,并且每个源仅需要一个连接,这提供了许多性能优势。
大多数 HTTP 传输都是短暂且突发的,而 TCP 已针对长期的批量数据传输进行了优化。通过重用同一连接,HTTP / 2 既可以更有效地利用每个 TCP 连接,又可以显着减少总体协议开销。此外,使用较少的连接会减少整个连接路径(换句话说,客户端,中介和原始服务器)的内存和处理占用空间。这样可以降低总体运营成本,并提高网络利用率和容量。因此,向 HTTP / 2 的迁移不仅应减少网络延迟,而且还有助于提高吞吐量并降低运营成本。
流量控制
流控制是一种机制,可以防止发送方用其可能不想要或无法处理的数据使接收方不知所措:接收方可能很忙,负载沉重,或者可能只愿意为特定资源分配固定数量的资源 / 流。
例如,客户端可能已请求具有高优先级的大型视频流,但是用户已暂停了视频,并且客户端现在希望暂停或限制其从服务器的传输,以避免获取和缓冲不必要的数据。针对这种问题,由于 HTTP / 2 流是在单个 TCP 连接中多路复用的,因此 TCP 流控制既不够精细,又没有提供必要的应用程序级 API 来调节各个流的传递。为了解决这个问题,HTTP / 2 提供了一组简单的构建块,它们允许客户端和服务器实现自己的流级别和连接级别的流控制:
DATA
帧时,该窗口就会减小,并通过WINDOW_UPDATE
接收器发送的帧来增加该窗口。SETTINGS
帧,这将在两个方向上设置流控制窗口的大小。流控制窗口的默认值设置为65,535字节,但是接收器可以设置较大的最大窗口大小(2^31-1
字节),并WINDOW_UPDATE
在接收到任何数据时通过发送帧来维护它。HTTP / 2 没有指定用于实现流控制的任何特定算法。取而代之的是,它提供了简单的构建块,并将实现推迟到客户端和服务器,可以使用它来实施自定义策略来规范资源使用和分配,以及实现可以帮助改善实际性能和感知性能的新交付功能。
服务器推送
HTTP / 2 的另一个强大新功能是服务器能够为单个客户端请求发送多个响应。也就是说,除了对原始请求的响应之外,服务器还可以将其他资源推送到客户端,而客户端不必显式地请求每个资源。
为什么在浏览器中需要这种机制?一个典型的 Web 应用程序由几十个资源组成,所有这些资源都由客户端通过检查服务器提供的文档来发现。结果,为什么不消除额外的延迟并让服务器提前推送相关资源?服务器已经知道客户端将需要哪些资源。那是服务器推送。
标头压缩
每个 HTTP 传输都带有一组标头,这些标头描述了所传输的资源及其属性。在 HTTP / 1.x 中,此元数据始终以纯文本形式发送,每次传输会增加 500-800 字节的开销,如果使用 HTTP cookie,则有时会增加数千字节。为减少此开销并提高性能,HTTP / 2 使用 HPACK 压缩格式压缩请求和响应头元数据,该格式使用两种简单但功能强大的技术:
霍夫曼编码允许在传输时压缩各个值,而先前传输的值的索引列表使我们可以通过传输索引值来编码重复值,该索引值可用于有效地查找和重建完整的标头键和值。
作为进一步的优化,HPACK 压缩上下文由静态和动态表组成:
静态表在规范中定义,并提供所有连接都可能使用的公共 HTTP 标头字段的列表(例如,有效标头名称);
动态表最初是空的,并根据特定连接中交换的值进行更新。
通过使用静态霍夫曼编码来处理以前从未见过的值,并用索引代替每一侧的静态或动态表中已经存在的值,可以减小每个请求的大小。
总结:
HTTP / 1.0 和HTTP / 1.1 的一些区别:
header
里的 If-Modified-Since, Expires
来做为缓存判断的标准,HTTP / 1.1 则引入了更多的缓存控制策略例如 Entity tag
,If-Unmodified-Since
, If-Match
, If-None-Match
等更多可供选择的缓存头来控制缓存策略;Connection: keep-alive
,一定程度上弥补了 HTTP/1.0 每次请求都要创建连接的缺点。HTTP / 2 与 HTTP / 1.1 有几处基本的不同
原文:https://www.cnblogs.com/rickiyang/p/13138574.html