1. 对比
HTTP 0.9 已过时
HTTP1.0:非持续连接,每个连接只处理一个请求响应事务,有些服务器端甚至还在用此,可以在一定时间内复用连接,具体复用时间的长短可以由服务器控制,一般在15s左右。
HTTP 1.1 默认使用持续连接,不必为每一个WEB对象建立一个新的连接,一个连接可以传送多个对象,但是服务器端可能还是会设置一个限制,太长时间没有读写事件,服务器可能关闭之。
HTTP 2.0 多路复用(一个域只要一个TCP连接)实现真正的并发请求,降低延时,提高了带宽的利用率。
在持久连接或者HTTP pipelining出现之前,每个连接的获取都需要创建一个独立的TCP连接。
2. 非持久连接示意
每个WEB对象都要建立新的连接。
假设某简单页面包含1个HTML,2个PNG图像,且都存储在一台服务器主机中。
客户端输入URL访问首页,http://www.abcdefg.com/path/index.html
第一步,客户端与服务器主机中的HTTP服务端口(默认为)建立TCP连接
第二步,客户端发送HTTP请求/path/index.html
第三步,服务器接收请求消息,从服务器主机内存或硬盘拿去拿对象/sompath/index.html,发出该对象的响应。
第四步,服务器告知TCP关闭这个TCP连接(TCP要等客户收到这个响应消息后,才会真正终止这个连接)。
第五步,HTTP客户接收响应消息。TCP连接终止。 该消息标明所拆装的对象是一个HTML文件。客户取出文件,分析后发现2个JPEG对象的引用。
第六步, 给每一个引用到的JPEG对象重复第一步到第四步
非持久连接,每个对象有2个RTT延迟
持久连接,带管道线,所有引用对象,共经历一个RTT延时;
持久连接,无管道线,每个引用对象一个RTT延时。
首先:HTTP的长连接和短连接本质上是TCP长连接和短连接。
1. 在HTTP1.0中,默认的是短连接,没有正式规定 Connection:Keep-alive 操作;
在HTTP1.1中所有连接都是Keep-alive的,也就是默认都是持续连接的(Persistent Connection)。
2. 两种的连接方式的区别如下图所示
3. 从上图可以看出,客户端与服务器建立持续连接后,在连接期间可以处理多个请求/响应(Request/Response)
HTTP权威指南:
HTTP/1.1 允许HTTP设备在事务处理结束以后将TCP连接保持在打开状态,后面的HTTP Request/Response 依然可以通过这个TCP连接继续传送。
在事务结束之后仍然保持在打开状态的TCP连接成为持久链接。非持久连接会在每个事务结束后关闭,持久连接会在不同事务(Request/Response)之间保持打开状态,直到客户端或服务器决定将其关闭为止。
可以提高HTTP连接性能的方法:
并行连接
通过多条连接发起并发的HTTP请求。并行连接可以提高复合页面的传输速度,但其连接也有一些缺点
每个事务都会打开/关闭一条新的连接,会耗费时间和带宽。由于TCP慢启动特性存在,每条连接的性能都会有所降低。可打开的并行连接数量实际上是有限的
持久化连接
Web客户端经常会打开到同一个站点的连接。比如,一个Web页面上的大部分内嵌图片通常来自同一个Web站点,而且相当一部分指向其他对象的超链通常都指向同一个站点。初始化了对某服务器HTTP请求的应用程序很可能会不久的将来对那台服务器发起更多的请求,这种性质称为站点局部性。
因此,HTTP/1.1允许HTTP设备在事务处理结束之后将TCP连接保持在打开状态,以便为未来的HTTP请求重用现存的连接。在事务处理结束之后仍然保持在打开状态的TCP连接称之为持久连接。持久连接会在不同事务之间保持打开状态,直到客户端或服务器决定其关闭为之。重用已对目标服务器打开的空闲持久连接,就可以避开缓慢的连接建立阶段。而且,已经打开的连接还可以避免慢启动的拥塞适应阶段,以便更快速地进行数据传输。所以,持久连接降低了时延和连接建立的开销,将连接保持在已调谐状态,而且减少了打开连接的潜在数量。
持久连接和并行连接配合使用可能是最高效的方式。很多Web应用程序都会打开少量的并行连接,其中每个都是持久连接。持久连接有两种类型
1)HTTP/1.0 + keep-alive 连接
2) HTTP/1.1 + persistent 连接
HTTP/1.0 keep-alive连接
现在很多客户端和服务器仍然在使用这些早期的keep-live连接。
实现HTTP/1.0 keep-live连接的客户端可以通过包含Connection:Keep-Alive 的请求头将一条连接保持在打开状态。
如果服务器愿意为下一条请求将连接保持在打开状态,就在响应头中说明,如果响应头中没有Connection:Keep-Alive ,客户端就认为服务器不支持keep-live,会在发回响应报文后关闭连接。
响应中Keep-Alive首部是可选的,但只有在提供Connection:Keep-Alive时才能使用它。
Connection:Keep-Alive
Keep-Alive:max=5,timeout=120
这个例子说明了服务器最多还会为另外5个事务保持连接的打开状态,或者将打开状态保持到连接空闲了2分钟以后。
注意:
1 在HTTP/1.0中,keep-alive并不是默认使用的。客户端必需发送一个Connection:Keep-Alive 请求首部来激活keep-alive连接。
2 如果服务器愿意为下一条请求将连接保持在打开状态,就在响应头中说明,如果响应头中没有Connection:Keep-Alive ,客户端就认为服务器不支持keep-live,会在发回响应报文后关闭连接。
3 只有在无需检测到连接的关闭就可以确定报文实体主体部分长度的情况下,才能将连接保持在打开状态--也就是说实体的主体部分必需有正确的Content-Length,
有多部件媒体类型(multipart/form-data ? 有boundary)或者用分块传输编码的方式进行了编码。在一条keep-live信道中回送错误的Content-Length是很糟糕的事情,这样的话,事务处理的另一端就无法精确地检测出一条报文的结束和另一条报文的开始了。
HTTP/1.1 持久连接 Persistent Connection
HTTP/1.1逐渐停止了对keep-alive连接的支持,用一种名为持久连接的改进型设计取代了它。持久连接的目的与keep-alive连接的目的相同,但是工作机制更优些。HTTP/1.1就吃连接在默认情况下是激活的,除非特别指明,否则HTTP/1.1假定所有的连接都是持久的。要想在事务处理结束之后将连接关闭,HTTP/1.1应用程序必须向报文中显示地添加一个Connection:close首部。
HTTP1.1客户端加载在收到响应后,除非响应中包含了Connection:close首部,不然HTTP/1.1连接就仍然维持在打开状态。但是,客户端和服务器仍然可以随时关闭空闲的连接。不发送Connection:close并不意味这服务器承诺永远将连接保持在打开状态。
注意:
1 只有当连接所有的报文都有正确的、自定义报文长度时,也就是说,实体主体部分的长度都和相应的Content-Length一致,或者用分块传输编码方式编码的,连接才能持久保持。
2 如果客户端不想在连接上发送其他请求了,就应该在最后一条请求中发送一个Connection:close请求首部
管道化连接
HTTP/1.1允许在持久连接上可选的使用请求管道。是相对于keep-alive连接的又一性能优化。在响应到达之前,可以将多条请求放入队列,当第一条请求通过网络流向服务器时,第二条和第三条请求也可以开始发送了。在高时延网络条件下,这样做可以降低网络的环回时间,提高性能。
对管道连接的说明:
1)如果HTTP客户端无法确认连接是持久的,就不应该使用管道
2)必须按照与请求相同的顺序回送HTTP响应。
3)HTTP客户端必须做好连接会在任意时刻关闭的准备,还要准备好重发所有未完成管道化的请求。
4)出错的时候,管道连接会阻碍客户端了解服务器执行的是一些列管道化请求中的哪一些。由于无法安全地重试POST这样的非幂请求,所以出错时,就存在某些方法永远不会被执行的风险。