http协议各个版本

1、HTTP协议版本更替

HTTP/0.9

        HTTP协议的最第一版本,功能简陋,仅支持请求方式GET,而且仅能请求访问HTML格式的资源。javascript

HTTP/1.0    

请求行必须在尾部添加协议版本字段(http/1.0);必须包含头消息        css

在0.9版本上作了进步,增长了请求方式POST和HEAD;再也不局限于0.9版本的HTML格式,根据Content-Type能够支持多种数据格式,即MIME多用途互联网邮件扩展,例如text/html、image/jpeg等;同时也开始支持cache,就是当客户端在规定时间内访问统一网站,直接访问cache便可。html

再次,HTTP请求和回应的格式也变了。除了数据部分,每次通讯都必须包括头信息(HTTP header),用来描述一些元数据。java

其余的新增功能还包括状态码(status code)、多字符集支持、多部分发送(multi-part type)、权限(authorization)、缓存(cache)、内容编码(content encoding)等。web

        可是1.0版本的工做方式是每次TCP链接只能发送一个请求,当服务器响应后就会关闭此次链接,下一个请求须要再次创建TCP链接,就是不支持keepalive。浏览器

        TCP链接的新建成本很高,由于须要客户端和服务器三次握手,而且开始时发送速率较慢(slow start)。因此,HTTP 1.0版本的性能比较差。随着网页加载的外部资源愈来愈多,这个问题就愈发突出了。缓存

为了解决这个问题,有些浏览器在请求时,用了一个非标准的Connection字段。性能优化

 
  1.  
  2. Connection: keep-alive服务器

这个字段要求服务器不要关闭TCP链接,以便其余请求复用。服务器一样回应这个字段。网络

 
  1.  
  2. Connection: keep-alive

一个能够复用的TCP链接就创建了,直到客户端或服务器主动关闭链接。可是,这不是标准字段,不一样实现的行为可能不一致,所以不是根本的解决办法。

Content-Type 字段

关于字符的编码,1.0版规定,头信息必须是 ASCII 码,后面的数据能够是任何格式。所以,服务器回应的时候,必须告诉客户端,数据是什么格式,这就是Content-Type字段的做用。

下面是一些常见的Content-Type字段的值。

  • text/plain
  • text/html
  • text/css
  • image/jpeg
  • image/png
  • image/svg+xml
  • audio/mp4
  • video/mp4
  • application/javascript
  • application/pdf
  • application/zip
  • application/atom+xml

这些数据类型总称为MIME type,每一个值包括一级类型和二级类型,之间用斜杠分隔。

除了预约义的类型,厂商也能够自定义类型。

 
  1.  
  2. application/vnd.debian.binary-package

上面的类型代表,发送的是Debian系统的二进制数据包。

MIME type还能够在尾部使用分号,添加参数。

 
  1.  
  2. Content-Type: text/html; charset=utf-8

上面的类型代表,发送的是网页,并且编码是UTF-8。

客户端请求的时候,可使用Accept字段声明本身能够接受哪些数据格式。

 
  1.  
  2. Accept: */*

上面代码中,客户端声明本身能够接受任何格式的数据。

MIME type不只用在HTTP协议,还能够用在其余地方,好比HTML网页。

 
  1.  
  2. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

  3. <!-- 等同于 -->

  4. <meta charset="utf-8" />

Content-Encoding 字段

因为发送的数据能够是任何格式,所以能够把数据压缩后再发送。Content-Encoding字段说明数据的压缩方法。

 
  1.  
  2. Content-Encoding: gzip

  3. Content-Encoding: compress

  4. Content-Encoding: deflate

客户端在请求时,用Accept-Encoding字段说明本身能够接受哪些压缩方法。

 
  1.  
  2. Accept-Encoding: gzip, deflate

HTTP/1.1    

1.1 版的最大变化,就是引入了持久链接(persistent connection),即TCP链接默认不关闭,能够被多个请求复用,不用声明Connection: keep-alive。解决了1.0版本的keepalive问题,1.1版本加入了持久链接,一个TCP链接能够容许多个HTTP请求;

客户端和服务器发现对方一段时间没有活动,就能够主动关闭链接。不过,规范的作法是,客户端在最后一个请求时,发送Connection: close,明确要求服务器关闭TCP链接。

 
  1.  
  2. Connection: close

目前,对于同一个域名,大多数浏览器容许同时创建6个持久链接。下降了延迟同时提升了带宽的利用率。

    

加入了管道机制,在同一个TCP链接里,容许多个请求同时发送,增长了并发性,进一步改善了HTTP协议的效率;举例来讲,客户端须要请求两个资源。之前的作法是,在同一个TCP链接里面,先发送A请求,而后等待服务器作出回应,收到后再发出B请求。管道机制则是容许浏览器同时发出A请求和B请求,可是服务器仍是按照顺序,先回应A请求,完成后再回应B请求。

Content-Length 字段

一个TCP链接如今能够传送多个回应,势必就要有一种机制,区分数据包是属于哪个回应的。这就是Content-length字段的做用,声明本次回应的数据长度。

 
  1.  
  2. Content-Length: 3495

上面代码告诉浏览器,本次回应的长度是3495个字节,后面的字节就属于下一个回应了。

在1.0版中,Content-Length字段不是必需的,由于浏览器发现服务器关闭了TCP链接,就代表收到的数据包已经全了。

分块传输编码

使用Content-Length字段的前提条件是,服务器发送回应以前,必须知道回应的数据长度。

对于一些很耗时的动态操做来讲,这意味着,服务器要等到全部操做完成,才能发送数据,显然这样的效率不高。更好的处理方法是,产生一块数据,就发送一块,采用"流模式"(stream)取代"缓存模式"(buffer)。

所以,1.1版规定能够不使用Content-Length字段,而使用"分块传输编码"(chunked transfer encoding)。只要请求或回应的头信息有Transfer-Encoding字段,就代表回应将由数量未定的数据块组成。

 
  1.  
  2. Transfer-Encoding: chunked

每一个非空的数据块以前,会有一个16进制的数值,表示这个块的长度。最后是一个大小为0的块,就表示本次回应的数据发送完了。下面是一个例子。

 
  1.  
  2. HTTP/1.1 200 OK

  3. Content-Type: text/plain

  4. Transfer-Encoding: chunked

  5.  
  6. 25

  7. This is the data in the first chunk

  8.  
  9. 1C

  10. and this is the second one

  11.  
  12. 3

  13. con

  14.  
  15. 8

  16. sequence

  17.  
  18. 0

新增了请求方式PUT、PATCH、OPTIONS、DELETE等。

另外,客户端请求的头信息新增了Host字段,用来指定服务器的域名。在HTTP1.0中认为每台服务器都绑定一个惟一的IP地址,所以,请求消息中的URL并无传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上能够存在多个虚拟主机(Multi-homed Web Servers),而且它们共享一个IP地址。

 
  1.  
  2. Host: www.example.com

有了Host字段,就能够将请求发往同一台服务器上的不一样网站,为虚拟主机的兴起打下了基础。(实现了在一台WEB服务器上能够在同一个IP地址和端口号上使用不一样的主机名来建立多个虚拟WEB站点。也便是说,web server上的多个虚拟站点能够共享同一个ip和端口。)且请求消息中若是没有Host头域会报告一个错误(400 Bad Request)。

        虽然1.1版容许复用TCP链接,可是同一个TCP链接里面,全部的数据通讯是按次序进行的。服务端是按队列顺序处理请求的,服务器只有处理完一个回应,才会进行下一个回应。假如前面的请求处理时间很长,后面就会有许多请求排队等着,这样就形成了“队头阻塞”的问题;同时HTTP是无状态的链接,所以每次请求都须要添加剧复的字段,下降了带宽的利用率。

多路复用带来一个新的问题是,在链接共享的基础之上有可能会致使关键请求被阻塞。SPDY容许给每一个request设置优先级,这样重要的请求就会优先获得响应。好比浏览器加载首页,首页的html内容应该优先展现,以后才是各类静态资源文件,脚本文件等加载,这样能够保证用户能第一时间看到网页内容。

为了不这个问题,只有两种方法:一是减小请求数,二是同时多开持久链接。这致使了不少的网页优化技巧,好比合并脚本和样式表、将图片嵌入CSS代码、域名分片(domain sharding)等等。若是HTTP协议设计得更好一些,这些额外的工做是能够避免的。

100(Continue) Status(节约带宽)

HTTP/1.1加入了一个新的状态码100(Continue)。客户端事先发送一个只带头域的请求,若是服务器由于权限拒绝了请求,就回送响应码401(Unauthorized);若是服务器接收此请求就回送响应码100,客户端就能够继续发送带实体的完整请求了。100 (Continue) 状态代码的使用,容许客户端在发request消息body以前先用request header试探一下server,看server要不要接收request body,再决定要不要发request body。

HTTP/1.1在1.0的基础上加入了一些cache的新特性,当缓存对象的Age超过Expire时变为stale对象,cache不须要直接抛弃stale对象,而是与源服务器进行从新激活(revalidation)。

HTTP 1.1支持只发送header信息(不带任何body信息),若是服务器认为客户端有权限请求服务器,则返回100,不然返回401。客户端若是接受到100,才开始把请求body发送到服务器。这样当服务器返回401的时候,客户端就能够不用发送请求body了,节约了带宽。

HTTP1.1还有身份认证机制,许多web站点要求用户提供一个用户名—口令对才能访问存放在其服务器中的文档,这种要求称为身份认证(authentication)。HTTP提供特殊的状态码和头部来帮助Web站点执行身份认证。

HTTP支持传送内容的一部分。这样当客户端已经有一部分的资源后,只须要跟服务器请求另外的部分资源便可。这是支持文件断点续传的基础。

HTTP/1.1支持文件断点续传,RANGE:bytes,HTTP/1.0每次传送文件都是从文件头开始,即0字节处开始。RANGE:bytes=XXXX表示要求服务器从文件XXXX字节处开始传送,断点续传。即返回码是206(Partial Content)

在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。

HTTP/2.0

        为了解决1.1版本利用率不高的问题,提出了HTTP/2.0版本。增长双工模式,即不只客户端可以同时发送多个请求,服务端也能同时处理多个请求,解决了队头堵塞的问题(HTTP2.0使用了多路复用的技术,作到同一个链接并发处理多个请求,并且并发请求的数量比HTTP1.1大了好几个数量级);HTTP请求和响应中,状态行和请求/响应头都是些信息字段,并无真正的数据,所以在2.0版本中将全部的信息字段创建一张表,为表中的每一个字段创建索引,客户端和服务端共同使用这个表,他们之间就以索引号来表示信息字段,这样就避免了1.0旧版本的重复繁琐的字段,并以压缩的方式传输,提升利用率。

        另外也增长服务器推送的功能,即不经请求服务端主动向客户端发送数据。

当前主流的协议版本仍是HTTP/1.1版本。

二进制协议

HTTP/1.1 版的头信息确定是文本(ASCII编码),数据体能够是文本,也能够是二进制。HTTP/2 则是一个完全的二进制协议,头信息和数据体都是二进制,而且统称为"帧"(frame):头信息帧和数据帧。

二进制协议的一个好处是,能够定义额外的帧。HTTP/2 定义了近十种帧,为未来的高级应用打好了基础。若是使用文本实现这种功能,解析数据将会变得很是麻烦,二进制解析则方便得多。

多工

HTTP/2 复用TCP链接,在一个链接里,客户端和浏览器均可以同时发送多个请求或回应,并且不用按照顺序一一对应,这样就避免了"队头堵塞"。

举例来讲,在一个TCP链接里面,服务器同时收到了A请求和B请求,因而先回应A请求,结果发现处理过程很是耗时,因而就发送A请求已经处理好的部分, 接着回应B请求,完成后,再发送A请求剩下的部分。

这样双向的、实时的通讯,就叫作多工(Multiplexing)。

数据流

由于 HTTP/2 的数据包是不按顺序发送的,同一个链接里面连续的数据包,可能属于不一样的回应。所以,必需要对数据包作标记,指出它属于哪一个回应。

HTTP/2 将每一个请求或回应的全部数据包,称为一个数据流(stream)。每一个数据流都有一个独一无二的编号。数据包发送的时候,都必须标记数据流ID,用来区分它属于哪一个数据流。另外还规定,客户端发出的数据流,ID一概为奇数,服务器发出的,ID为偶数。

数据流发送到一半的时候,客户端和服务器均可以发送信号(RST_STREAM帧),取消这个数据流。1.1版取消数据流的惟一方法,就是关闭TCP链接。这就是说,HTTP/2 能够取消某一次请求,同时保证TCP链接还打开着,能够被其余请求使用。

客户端还能够指定数据流的优先级。优先级越高,服务器就会越早回应。

头信息压缩

HTTP 协议不带有状态,每次请求都必须附上全部信息。因此,请求的不少字段都是重复的,好比CookieUser Agent,如出一辙的内容,每次请求都必须附带,这会浪费不少带宽,也影响速度。

HTTP/2 对这一点作了优化,引入了头信息压缩机制(header compression)。一方面,头信息使用gzipcompress压缩后再发送;另外一方面,客户端和服务器同时维护一张头信息表,全部字段都会存入这个表,生成一个索引号,之后就不发送一样字段了,只发送索引号,这样就提升速度了。

服务器推送

HTTP/2 容许服务器未经请求,主动向客户端发送资源,这叫作服务器推送(server push)。

意思是说,当咱们对支持HTTP2.0的web server请求数据的时候,服务器会顺便把一些客户端须要的资源一块儿推送到客户端,省得客户端再次建立链接发送请求到服务器端获取。这种方式很是合适加载静态资源。

服务器端推送的这些资源其实存在客户端的某处地方,客户端直接从本地加载这些资源就能够了,不用走网络,速度天然是快不少的。

常见场景是客户端请求一个网页,这个网页里面包含不少静态资源。正常状况下,客户端必须收到网页后,解析HTML源码,发现有静态资源,再发出静态资源请求。其实,服务器能够预期到客户端请求网页后,极可能会再请求静态资源,因此就主动把这些静态资源随着网页一块儿发给客户端了。

服务端推送能把客户端所须要的资源伴随着index.html一块儿发送到客户端,省去了客户端重复请求的步骤。正由于没有发起请求,创建链接等操做,因此静态资源经过服务端推送的方式能够极大地提高速度。

普通的客户端请求过程:

服务端推送的过程:

HTTP 性能优化的关键并不在于高带宽,而是低延迟。TCP 链接会随着时间进行自我「调谐」,起初会限制链接的最大速度,若是数据成功传输,会随着时间的推移提升传输的速度。这种调谐则被称为 TCP 慢启动(拥塞控制)。因为这种缘由,让本来就具备突发性和短时性的 HTTP 链接变的十分低效。
HTTP/2 经过让全部数据流共用同一个链接,能够更有效地使用 TCP 链接,让高带宽也能真正的服务于 HTTP 的性能提高。

2、HTTP响应模型

        服务器收到HTTP请求以后,会有多种方法响应这个请求,下面是HTTP响应的四种模型:

        单进程I/O模型

服务端开启一个进程,一个进程仅能处理一个请求,而且对请求顺序处理;

        多进程I/O模型

服务端并行开启多个进程,一样的一个进程只能处理一个请求,这样服务端就能够同时处理多个请求;

        复用I/O模型

服务端开启一个进程,可是呢,同时开启多个线程,一个线程响应一个请求,一样能够达到同时处理多个请求,线程间并发执行;

        复用多线程I/O模型

服务端并行开启多个进程,同时每一个进程开启多个线程,这样服务端能够同时处理进程数M*每一个进程的线程数N个请求。

相关文章
相关标签/搜索