当前位置: 首页 > 科技观察

每个Web开发人员都应该了解的HTTP-2

时间:2023-03-18 01:33:34 科技观察

自从我写了上一篇博文以来,我一直没有时间写。今天我终于抽出时间来写一些关于HTTP的东西。我想每个Web开发者都应该对支持整个Web世界的HTTP协议有所了解,这样才能帮助大家更好的完成开发任务。在本文中,我将讨论HTTP是什么、它是如何产生的、它的状态以及我们应该如何使用它。什么是HTTP首先我们需要了解什么是HTTP。HTTP是基于TCP/IP的应用层通信协议,是客户端和服务器在Internet上相互通信的标准。它定义了如何通过Internet请求和传输内容。HTTP是在应用层抽象出来的标准,使主机(客户端和服务器)之间的通信能够通过TCP/IP进行请求和响应。TCP默认使用的端口是80,当然也可以使用其他端口,比如HTTPS使用443端口。HTTP/0.9-一行协议(1991)HTTP最早的规范可以追溯到1991年。在当时的版本是HTTP/0.9,极其简单,只有一种请求方式,叫GET。如果客户端想要访问服务器上的某个页面,只需要一个非常简单的请求如下:GET/index.html服务器对应的返回类似如下:(responsebody)(connectionclosed)就这么简单,server捕获到请求立即返回HTML并关闭连接,里面没有头部(headers)只有GET这种请求方式必须返回HTML可以看到,当时的HTTP协议只是一个基本的垫脚石。HTTP/1.0-19961996年,新版本的HTTP比以前的版本有了很大的改进,也被命名为HTTP/1.0。与HTTP/0.9只能返回HTML不同,HTTP/1.0支持处理多种返回格式,例如图像、视频、文本或其他格式的文件。还增加了更多的请求方式(如POST和HEAD),请求和响应的格式也相应发生了变化,都增加了头信息;引入状态代码来定义返回的特征;引入了字符集支持;支持多部分类型(multi-part)、用户认证信息、缓存、内容编码格式等。一个简单的HTTP/1.0请求看起来像这样:GET/HTTP/1.0Host:kamranahmed.infoUser-Agent:Mozilla/5.0(Macintosh;IntelMacOSX10_10_5)Accept:*/*如您所见,该请求附带了一些个人信息客户端,响应类型要求等。这些在HTTP/0.9中是不可能的,因为那时候没有标头。对上述请求的响应示例如下:HTTP/1.0200OKContent-Type:text/plainContent-Length:137582Expires:Thu,05Dec199716:00:00GMTLast-Modified:Wed,5August199615:55:28GMTServer:Apache0.84(responsebody)(connectionclosed)从HTTP/1.0的早期开始(HTTP后跟版本号),在状态码200之后附加了一个原因短语(你可以用来描述状态码)。在这个较新的版本中,头信息请求和响应的内容仍然必须是ASCII编码,但是响应的内容可以是任何类型,比如图片、视频、HTML、文本或其他类型,服务端可以返回任何内容给客户端。所以在那之后,HTTP中的“超文本”就变成了一个误称。HMTP(超媒体传输协议)可能更有意义,但我想我们会坚持使用该名称。HTTP/1.0的一个主要缺点是它不能在一个连接中有多个请求。这意味着当客户端需要从服务器获取某些东西时,必须建立新的TCP连接,并在处理完单个请求后关闭连接。当您需要下一件事情时,您必须重新建立新的连接。这样做的缺点在哪里?假设你要访问一个页面,有10张图片、5个样式表(stylesheet)和5个JavaScript,一共20个文件要完整显示。由于一个连接在处理完一个请求后关闭,因此会有20个独立的连接,每个文件将通过其自己的连接单独处理。当连接数变大时,会面临严重的性能问题,因为TCP启动需要三次握手,启动缓慢。三向握手三向握手是一种简单的模型,所有的TCP连接在传输应用数据之前都需要在三向握手中传输一系列数据包。SYN-客户端选择一个随机数,我们称之为x,并将其发送到服务器。SYNACK-服务器响应相应请求的ACK包中包含一个服务器随机生成的数字,我们称之为y,返回客户端发送给客户端的x+1。ACK——客户端从服务器收到y后,将y加1作为ACK包返回给服务器。一旦三次握手完成,客户端和服务器就可以开始交换数据了。值得注意的是,当客户端发送完最后一个ACK数据包后,可以立即将申请数据包发送给服务器,而服务器需要等到收到ACK数据包后才会接受申请数据包。请注意,上图有点问题。客户端最后发回的ACK包只包含y+1。上图应该是ACK:y+1而不是ACK:x+1,y+1。然而,一些HTTP/1.0的实现试图通过引入一个名为Connection:keep-alive的新标头来克服这个问题,这意味着告诉服务器“嘿服务器,请不要关闭此连接,我仍然想使用它“。然而,这并没有得到广泛支持,问题依然存在。除了无连接之外,HTTP还是一种无状态协议,即服务器不维护有关客户端的任何信息。因此,每个请求都必须给服务器完成请求所必需的信息,并且每个请求都与之前的旧请求无关。因此,这会火上浇油。除了需要创建大量的新连接外,客户端还需要在每个连接中发送大量重复的数据,从而导致带宽的大量浪费。HTTP/1.1-1999HTTP/1.0仅仅3年后,下一个版本HTTP/1.1于1999年发布,改进了其前身的许多问题。主要改进包括:增加了许多HTTP请求方法,包括PUT、PATCH、HEAD、OPTIONS、DELETE。主机标识符Host在HTTP/1.0中不是必需的,但在HTTP/1.1中是必需的。如上所述的持久连接。在HTTP/1.0中,每个连接只有一个请求,并且在该请求之后立即关闭,这会导致性能问题并增加延迟。HTTP/1.1引入了持久连接,即连接默认不关闭,保持打开状态,允许多个连续的请求使用这个连接。关闭连接只需要在header信息后面加上Connection:close即可。客户端通常会在最后一次请求中发送此标头信息以安全关闭连接。新版本还引入了“流水线”支持,客户端可以在同一个连接中向服务器发送多个请求,而无需等待服务器返回响应,并且服务器发送请求的顺序必须与收到的请求响应相同。但是你可能会问,客户端怎么知道第一个响应是从哪里下载的,下一个响应的内容是从哪里开始的呢?要解决这个问题,header信息必须要有Content-Length,客户端可以根据这个来判断哪个响应结束了,就可以开始等待下一个响应了。.值得注意的是,为了从持久连接或流水线中受益,必须包含Content-Length标头,因为这将让客户端知道传输何时完成,然后才能发送下一个请求(在持久连接中,从Send开始以正常顺序顺序请求)或开始等待下一个响应(当启用流水线时)。.但是,这种方法仍然存在问题。也就是说,如果数据是动态的,服务器无法提前知道内容长度怎么办?那么在这种情况下,你能不能从这个方法中受益呢?为了解决这个问题,HTTP/1.1引入了分块编码。在这种情况下,服务器可能会忽略Content-Length以支持分块编码(这更常见)。但是,如果它们都不可用,则必须在请求结束时关闭连接。在使用动态内容的分块传输的情况下,当服务器开始传输但无法获取Content-Length时,它可能会开始分块发送内容(逐块)并将Content-Length添加到每个小块中转移。当所有的chunk发送完毕,即整个传输完成后,发送一个空的小chunk,比如设置Content-Length为0,让客户端知道传输完成。为了通知客户端分块传输,服务器在标头中包含Transfer-Encoding:chunked。与HTTP/1.0只有Basic认证不同,HTTP/1.1包括摘要认证和代理认证。缓存。范围请求(字节范围)。字符集。内容协商。客户端cookie。支持压缩。新的状态代码。等。我不打算在这里讨论HTTP/1.1的所有特性,因为您可以找到很多围绕该主题的讨论。我建议您阅读HTTP/1.0和HTTP/1.1版本之间的主要区别,并希望阅读原始RFC以了解更多信息。HTTP/1.1于1999年推出,多年来一直是标准。虽然,比上一代好多了,但是网络日新月异,老了。与以前相比,加载网页是一项资源密集型任务,打开一个简单的网页已经需要30多个连接。你可能会说,HTTP/1.1有持久连接,为什么会有这么多连接?原因是HTTP/1.1在任何时候都只能有一个未完成的连接。HTTP/1.1试图通过引入流水线来解决这个问题,但并没有彻底解决。因为一旦管道遇到一个慢请求或者一个巨大的请求,后面的请求就会被阻塞,必须等待前面的请求完成。为了克服HTTP/1.1的这些缺点,开发人员开始实施一些解决方法,例如使用spritesheet、在CSS中编码图像、单个巨型CSS/JavaScript文件、域分片等。SPDY-2009年Google走在了行业的前沿。为了让网络更快,提高网络安全,减少网页等待时间,他们开始尝试替代协议。2009年,他们宣布推出SPDY。SPDY是Google的商标,而不是首字母缩写词。很明显,如果我们继续增加带宽,一开始可以提升网络性能,但到一定阶段后性能提升就非常有限了。但是如果把这些优化放在等待时间上,比如减少等待时间,就会有持续的性能提升。这是SPDY优化前协议的核心思想,减少等待时间来提升网络性能。对于那些不知道区别的人来说,延迟是延迟,数据从源传输到目的地需要多长时间(以毫秒为单位),而带宽是每秒传输的数据量(比特每秒)。SPDY的特性包括:多路复用、压缩、优先级、安全性等,关于SPDY的细节我就不展开了。在下一章介绍HTTP/2的时候,这些都会提到,因为HTTP/2的大部分特性都是从SPDY中得到启发的。SPDY并没有试图取代HTTP,它是在应用层HTTP之上的传输层,它只是在发送请求之前修改请求。它开始成为事实上的标准,大多数浏览器都开始支持它。2015年,Google不想有两个相互竞争的标准,所以他们决定将其合并到HTTP协议中,这导致了HTTP/2的出现和SPDY的弃用。HTTP/2-2015现在你可能明白为什么我们需要另一个版本的HTTP协议了。HTTP/2专为低延迟内容交付而设计。与HTTP/1.1的主要特性和差异包括:使用二进制而不是纯文本多路复用-多个异步HTTP请求可以使用单个连接标头使用HPACK服务器推送进行压缩-单个请求多个响应请求优先级安全性1.二进制协议HTTP/2解决了延迟问题通过使HTTP/1.x成为二进制协议来解决HTTP/1.x中的问题。作为二进制协议,它更容易解析,但可读性不如HTTP/1.x。帧和流的概念构成了HTTP/2的主要部分。帧和流HTTP消息现在由一个或多个帧组成。HEADERS帧携带元数据,DATA帧携带内容。还有其他类型的帧(HEADERS、DATA、RST_STREAM、SETTINGS、PRIORITY等),您可以通过HTTP/2规范了解它们。每个HTTP/2请求和响应都被赋予一个唯一的流ID并被分割成帧。帧是一小段二进制数据。帧的集合称为流,每个帧都有一个流ID来标识它所属的流,因此同一流下的每个帧都有一个共同的头。值得注意的是,除了流ID唯一之外,客户端发起的请求使用奇数作为流ID,服务器响应使用偶数作为流ID。除了HEADERSframe和DATAframe,还有一个值得一提的frame是RST_STREAM。这是一种用于中止流的特殊帧类型,即客户端可以发送此帧让服务器知道,我不再需要此流。在HTTP/1.1中,服务器停止向客户端发送响应的唯一方法是关闭连接,这会导致延迟增加,因为必须打开一个新请求才能稍后发送请求。然而,在HTTP/2中,客户端可以使用RST_STREAM停止接收特定流,同时连接保持打开状态以供其他请求使用。2.多路复用因为HTTP/2是一个二进制协议,并且如上所述它使用帧和流来传输请求和响应,一旦建立了TCP连接,同一连接内的所有流都可以通过这个TCP连接异步发送,而无需另外打开连接。相反,服务器可以以相同的异步方式返回响应,这意味着这些响应可以是无序的,客户端使用分配的流ID来识别数据包所属的流。这也解决了HTTP/1.x中请求管道阻塞的问题,即客户端不必等待耗时的请求,而其他请求仍然可以处理。3.HPACK请求头压缩RFC花一篇文档介绍了发送头信息的优化。其实质是当我们在同一个客户端上连续访问服务器时,header中存储了很多冗余数据。重复发送,有时只是cookie会增加标头的大小,这会占用大量带宽并增加传输延迟。为了解决这个问题,HTTP/2引入了头部压缩。与请求和响应不同,标头中的信息未使用gzip或compress等格式进行压缩。相反,使用不同的机制来压缩标头信息。客户端和服务端同时维护一个头信息表,存储头信息使用哈夫曼编码编码后的值,如果后续请求中出现相同的头信息字段,则忽略重复值(如useragent(useragent)等),并且只发送存储在双方信息表中的引用。我们说的头信息和HTTP/1.1一样,都是在这个基础上增加了一些伪头信息,比如:scheme、:host和:path。4.服务器推送服务器推送是HTTP/2的另一大特性。对于服务器来说,当它知道客户端需要某些资源时,它可以向客户端推送数据,即使客户端没有请求。例如,假设浏览器加载网页时,解析整个页面,发现必须从服务器获取一些内容,然后向服务器发送相应的请求以获取该内容。服务器推送减少了传输此数据所需的往返请求数。它是怎么做到的?服务器通过发送一个名为PUSH_PROMISE的特殊帧来通知客户端“嘿,我要把这个资源发给你,不要再问我了。”这个PUSH_PROMISE帧是和push相关的stream链接在一起的,包含了要推送的streamID,也就是说这个stream会被服务器推送给客户端。5.请求优先级当流打开时,客户端可以在HEADERS帧中包含优先级信息来指定流的优先级。在任何时候,客户端都可以发送PRIORITY帧来更改流的优先级。在没有任何优先级信息的情况下,服务器将无序地异步处理这些请求。如果流被分配了一个优先级,服务器将使用这个优先级来确定它需要分配多少资源来处理请求。6.安全性关于是否强制使用TLS来增加安全性的讨论范围很广,讨论的结果是它不是强制性的。但是,大多数供应商在使用TLS时只能使用HTTP/2。因此,虽然HTTP/2在规范中没有要求加密,但是加密已经按照惯例建立起来了。通过这种方式,在TLS之上实现HTTP/2有一些强制性要求。例如,最新版本的TLS是1.2,必须达到一定级别的最大密钥大小,需要部署临时密钥等等。到现在HTTP/2已经完全超过了SPDY,并且还在增长。HTTP/2有很多关系性能改进,我们应该开始部署它。如果你想更深入地了解细节,这里是规范的链接和HTTP/2性能改进演示的链接。请在留言板上写下您的问题或意见,***如有发现错误,也请留言指出。就这些了,回头见~