1、HTTP/1.0css
HTTP1.0版本的Keep-alive并不像HTTP1.1那样是默认发送的,因此要想链接获得保持,必须手动配置发送connection:keep-alive字段。若想断开keep-alive链接,需发送Connection:close字段html
注意:这里的链接是HTTP依赖的传输协议TCP,而不是HTTP自己。浏览器
为何须要长链接?服务器
长链接能够提升链接的利用效率,即HTTP能够复用一条链接。例如某个用户浏览一个网站,他很长一段时间才跳转到另外一个连接,彷佛保持长链接没有什么好处,很浪费资源。网络
但若是这个网站的并发量很大,保持长链接的好处就凸显了。若是每一个请求都须要创建新的TCP链接,那对服务器的开销是至关的。并发
创建链接报文首部格式:性能
Connection:Keep-Alive网站
Keep-Alive:timeout ; max #参数之间用;分号隔开设计
参数:max 最大处理事务数量代理
timeout 链接保持的时间,单位为秒
断开链接报文首部格式:
Connection:close
Keep-Alive的创建过程
客户端向服务器在发送请求报文同时在首部添加发送Connection字段》服务器收到请求并处理connection字段》服务器回送Connection:Keep-Alive字段给客户端》客户端接收到connection字段》Keep-Alive链接创建成功
服务端自动断开过程:
客户端向服务器只是发送内容报文(不包含Connection字段)》服务器收到请求并处理》服务器返回客户端请求的资源并关闭链接》客户端接收资源,发现没有Connection字段,断开链接
客户端请求断开链接过程:
客户端向服务器发送Connection:close字段》服务器收到请求并处理connection字段》服务器回送响应资源并断开链接》客户端接收资源并断开链接
事务:
在基于TCP链接的http协议中,一个事务表示客户端向服务端请求一个资源并获得响应返回的过程。这个资源多是html,css,js文件。
例如:
表示链接的最大处理事务数是5,链接时间是2分钟
Keep-Alive的限制和规则
(1)事务处理的接收端必须接收到发送端发送的正确的Content-Length字段,或者接收到MIME多部件多媒体类型(容许链接屡次发送不一样类型的资源)字段,或者接收到Chunked分块模式字段。以客户端向服务端发送资源为例(实际上,在一条HTTP信道上,数据传输是双向的,这里只是其中一种情形来说述)。在一个非Keep—Alive的链接中,每一次资源请求都须要建立一个HTTP链接,出错了重传不会担忧先后两次的Content-Length不相同问题。而若是是在Keep-Alive链接中,问题就没有那么简单了。想象一下出错客户端须要从新发送资源给服务端,而此时服务端端保存的可能仍是上一条错误报文的Content-Length(多是0),那么在接收新资源时候就会出现实体内容长度和content-length不一致等问题(这里存在了太多的细节问题)。
(2)不该该与没法肯定是否支持Connection首部的代理服务器创建keep-alive链接,以防止出现下面要介绍的哑代理问题。但实际应用中,这一点不是老是能作到。
哑代理问题
盲中继指的是一些自身没有处理Connection:Keep-Alive的能力代理服务器。当客户端向服务端发送Connection字段的时候,经过代理服务器,而代理服务器没有处理Connection字段,而只将其当一个扩展首部来处理,将报文原本来本发送给服务端,服务端接收到Connecton字段后回送Connection字段。这时代理服务器仍是原封不动将报文转送给客户端。此时客户端和服务器都创建了Keep-Alive链接,而代理服务器却绝不知情。它一直在等待客户端给它发送断开链接的字段,由于一个事务已经完成,已经没有必要保持链接了。这是创建了Keep-Alive链接客户端继续互相发送数据,而代理服务器收到的不是Connection:close字段,因此对此就会视而不见,就像‘盲’了同样。
根据《HTTP权威指南》中的描述,目前浏览器解决哑代理问题的一个解决方案使扩展首部字段Proxy-Connection,是由Netscape提出的。大体的实现原理是,客户端服务器会向代理服务器发送Proxy-Connection字段,若是对方是聪明的代理,它就会用Connection代替Proxy-Connection字段,发送给服务端,服务端接受到Connection字段以后就知道是要创建持久链接,这样客户端,代理,服务端三者都会明白须要创建一个持久链接。而若是对方是一个盲中继,它就会直接把Proxy-Connection当作扩展首部直接转发给服务端,服务端接收到后发现是Proxy-Connection字段,会自动忽略,也就是说不会创建持久链接,一般接下来事务完成以后就是直接关闭链接了。这样就不会产生上文所述的问题。
因为本人对这方面知识还接触比较少,在这里就不对Proxy-Connection做更深刻阐述了。
2、HTTP/1.1
客户端(浏览器)若是使用的是HTTP/1.1版本,默认会发送connection:keep alive字段
,若是没有特殊说明,TCP链接是默认保持的,而须要将一个链接关闭,则须要客户端发送Connection:close首部字段。
HTTP1.1通过版本的更迭,HTTP1.1逐渐中止了对Keep-alive链接的支持,用一种名为持久链接(persistent connection)的改进型机制设计取代了它。这种机制默认链接创建以后是持久的,也就是说客户端不须要依靠首部添加Keep-alive字段来保持链接。在但愿断开链接的时候,则须要客户端首部添加Connection:close字段。
持久链接的限制和规则:
(1)HTTP/1.1对代理服务器的要求更高,它必须能管理与客户端和服务端之间的持久链接。
(2)因为HTTP/1.1设备随时可能断开链接(由于出错;或者是链接空闲一段时间后,服务端作了逻辑处理,主动关闭;也多是其余缘由),客户端可能在没有接收到整条完整的响应,服务端就断开了链接。因此客户随时要作好从新发送请求的准备。
(3)一个用户客户端对任何服务器或者代理最多只能维持两条持久链接,以防止服务器过载。因此做为中间者身份的代理服务器可能须要更多到服务器的链接来支持并发的用户请求。例若有N个用户请求不一样的服务器,代理须要维护2N条到任意服务器或者父代理的链接。
管道化链接
HTTP/1.1容许在持久链接的基础上自由选择使用请求管道。管道的原理很像队列。在响应到达前,客户端发送的请求能够放进管道里面,当第一条请求发送到服务端而还客户端尚未接收到响应的时候,后面的请求能够接着发送了。为何能够这样?这就是管道的做用了,由于管道中的请求是‘提早准备好的’,它无需等待客户端判断已经接收到响应了再发送新的请求(这是非管道链接的串行请求)。在高时延的网络中,管道化链接有利于下降网络的环回时间,提升网络传输性能。
虽然管道化链接有它强大的优点,可是管道化链接也有它的局限性。
1)客户端的请求在管道中是有必定次序的。但因为HTTP报文是没有顺序,响应报文一旦次序出错,就没法与请求一一对应匹配起来。
2)通常来讲,非幂等性(例如POST请求,下文会讲述)请求是不但愿放进管道的。缘由是,管道传输中若是出现了错误,请求和响应的次序没法获得保障,在一些订单或者涉及资金的POST提交中,结果是灾难性的。
3)在管道传输过程当中,服务器关闭了链接,这时有许多没有完成的请求事务,那么客户端和服务端采起什么机制来确认已经处理和没有处理的事务这一问题值得商榷。客户端可能必须从新发送请求链接而且从新发送全部的管道中的请求。
3、重试和幂等性
当事务由于一条持续的链接的意外关闭而被终端,客户端须要从新发送请求。这种重试在管道化链接中更复杂。
一次HTTP请求的类型多是GET , POST , HEAD , PUT , DELETE , TRACE , OPTION,若是重试先后对服务端的数据没有很大影响的请求类型就是幂等性的。显然,POST是非幂等的。关于幂等性的更多讨论,能够看看这篇文章:https://www.jianshu.com/p/178da1e2903c
4、最后,关于链接的关闭:
何时控制性地关闭链接,以及如何关闭链接,以达到信道上最高效率的数据传输是一个值得研究和讨论的问题。《HTTP权威指南》中也没有提供一些可行的方案。之后有接触到相关知识,我会继续补充。
参考文章:https://www.jianshu.com/p/178da1e2903c