HTTP中的keepalive(长连接)

时间:2021-07-30 03:48:07

公司布置的调研,但是我竟然找错对象了。。。


keepalive 是一个用来检查两个设备之间的连接或者防止连接被破坏所发送的信息。

下面主要介绍HTTP协议中的keepalive


HTTP协议采用“请求-应答”模式,当使用普通模式,即非KeepAlive模式时,每个请求/应答客户和服务器都要新建一个连接,完成 之后立即断开连接(HTTP协议为无连接的协议);当使用Keep-Alive模式(又称持久连接、连接重用)时,Keep-Alive功能使客户端到服 务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive功能避免了建立或者重新建立连接。

http 1.0中默认是关闭的,需要在http头加入"Connection: Keep-Alive",才能启用Keep-Alive;http 1.1中默认启用Keep-Alive,如果加入"Connection: close ",才关闭。目前大部分浏览器都是用http1.1协议,也就是说默认都会发起Keep-Alive的连接请求了,所以是否能完成一个完整的Keep- Alive连接就看服务器设置情况。


从上面的分析来看,启用Keep-Alive模式肯定更高效,性能更高。因为避免了建立/释放连接的开销。

优势具体总结如下:

1. 通过减少打开和关闭TCP连接的次数,大大节省了主机的CPU时间,和用来处理TCP协议的blocks的内存

2. HTTP的请求和响应可以pipelined在一个连接里。管道化可以允许客户端发送多个请求而不用等待服务器的响应,可以使一个TCP的连接的空闲时间减少,从而提高利用率

3. 因为减少了建立TCP连接的次数,减少了互相发送的包,从而减少了网络的拥堵状况。

4. 因为不需要先握手,因此建立连接之后,发送信息的效率提高

5. HTTP协议可以进化的更优雅,因为当出错了之后,不用关闭TCP连接。客户端使用未来的HTTP协议的时候,可以享用新的特性,而如果连接到的是一个旧版本的服务器,也可以按照原来的版本一样,断开连接,回复错误。

同时,RFC 2616 还指出:单用户客户端与任何服务器或代理之间的连接数不应该超过2个。一个代理与其它服务器或代理之间应该使用不超过2 * N的活跃并发连接。这是为了提高HTTP响应时间,避免拥塞。



劣势

对于现在的广泛普及的宽带连接来说,Keep-Alive也许并不像以前一样有用。web服务器会保持连接若干秒(Apache中默认15秒),这与提高的性能相比也许会影响性能。

对于单个文件被不断请求的服务(例如图片存放网站),Keep-Alive可能会极大的影响性能,因为它在文件被请求之后还保持了不必要的连接很长时间。


web浏览器中的使用

网景导航者(4.05版本以后)和Internet Explorer(4.01版本以后)支持使用持久链接链接Web服务器和代理服务器。

网景不使用过时时间来关闭持久连接。而是对所有空闲的持久链接进行排队。当需要打开一个新的持久链接,但连接到不同的服务器上时,浏览器使用最近最少使用算法终止一个空闲的持久链接。

Internet Explorer支持持久链接,IE 6和IE 7缺省使用2个持久链接,而IE 8缺省使用6个持久链接。持久链接在不活跃60秒后过时,可以在Windows注册表中修改。

Mozilla Firefox支持持久链接。可以定制同时的持久连接的最大个数(每个服务器,每个代理服务器,总数)。连接在不活跃300秒(5分钟)后过时(配置中可以修改)。

Opera 4.0版本开始支持持久链接. 可以配置同时的持久连接的最大个数(每个服务器,总数)。 


如何获得消息的长度

RFC 2616 对 消息的长度总结如下:一个消息的transfer-length(传输长度)是指消息中的message-body(消息体)的长度。当应用了 transfer-coding(传输编码),每个消息中的message-body(消息体)的长度(transfer-length)由以下几种情况 决定(优先级由高到低):

   * 任何不含有消息体的消息(如1XXX、204、304等响应消息和任何头(HEAD,首部)请求的响应消息),总是由一个空行(CLRF)结束。

   * 如果出现了Transfer-Encoding头字段 并且值为非“identity”,那么transfer-length由“chunked” 传输编码定义,除非消息由于关闭连接而终止。

   * 如果出现了Content-Length头字段,它的值表示entity-length(实体长度)和transfer-length(传输长 度)。如果这两个长度的大小不一样(i.e.设置了Transfer-Encoding头字段),那么将不能发送Content-Length头字段。并 且如果同时收到了Transfer-Encoding字段和Content-Length头字段,那么必须忽略Content-Length字段。

   * 如果消息使用媒体类型“multipart/byteranges”,并且transfer-length 没有另外指定,那么这种自定界(self-delimiting)媒体类型定义transfer-length 。除非发送者知道接收者能够解析该类型,否则不能使用该类型。

   * 由服务器关闭连接确定消息长度。(注意:关闭连接不能用于确定请求消息的结束,因为服务器不能再发响应消息给客户端了。)


为了兼容HTTP/1.0应用程序,HTTP/1.1的请求消息体中必须包含一个合法的Content-Length头字段,除非知道服务器兼容 HTTP/1.1。一个请求包含消息体,并且Content-Length字段没有给定,如果不能判断消息的长度,服务器应该用400 (bad request) 来响应;或者服务器坚持希望收到一个合法的Content-Length字段,用 411 (length required)来响应。

所有HTTP/1.1的接收者应用程序必须接受“chunked” transfer-coding (传输编码),因此当不能事先知道消息的长度,允许使用这种机制来传输消息。消息不应该够同时包含 Content-Length头字段和non-identity transfer-coding。如果一个消息同时包含non-identity transfer-coding和Content-Length ,必须忽略Content-Length 。 


在headers中的定义

Keep-Alive           = "Keep-Alive" ":" 1#keep-alive-info

keep-alive-info      =   "timeout" "=" delta-seconds

                       / "max" "=" 1*DIGIT

                       / keep-alive-extension

keep-alive-extension = token [ "=" ( token / quoted-string ) ]

keep-alive在服务器和客户端两侧都可以发送

timeout 是当连接空闲多久之后关闭连接,如果服务器愿意,可以保持更久的时间。参数是一个用秒表示的int,

max 是客户端可以向服务器最多可以发送的请求数,或者服务器端能够接受请求数。一旦请求和响应的总数超过max,服务器可以关闭连接。

max从开始建立连接的时候开始计数。

对于客户端,可以使用这个参数去限制发送的请求,对于服务器端,可以使用这个参数去限制管道化信息的长度。

对于服务器端,当请求和响应已经满足max条件时,可以发送响应后,直接关闭连接

keep-alive-extentsion 可以添加多个自定义的值,如果服务器端对于发送过去的extension的认证失败,可以忽略这次请求。(大意如此)