http 持久链接

谈谈持久连接——用暴走漫画理解HTTP 原 

郭诗雨2  来自:NS测试部 time 2014-04-09 11:23 次 637

持久链接ajax

    什么是持久链接?顾名思义,就是"持久"的链接。以前说到过,为了完成一个HTTP事务,服务器和客户端之间要创建一条TCP链接来传输报文,这个事务结束之后通常都会直接把它关闭,这是正常的模式。但是这样会形成网络使用效率的下降,为何呢?有这么几点缘由浏览器

  1. 每次创建链接的时候都要通过三次握手等必须的程序,若是咱们拥有一条能够一直使用的链接的话,也就意味着咱们只须要进行一次链接的创建,这就省去了每次创建链接的时间。服务器

  2. 上一篇心得中提到过了,使用过的链接会比新创建的链接速度会快一些,这是因为TCP链接慢启动的特性,每次创建新的链接,固然不如已经被调教的很好的链接速度快咯。网络

  3.  每一个链接对于服务器和客户端来讲都是负担,能少开尽可能少开,固然是在不影响功能和体验的前提下。post

     如今不少方案都会采用持久链接+新链接结合的方式,这种方式尽量的减小了新建链接的浪费,同时当现有链接没有办法知足需求的时候,能够创建新链接知足需求,比较灵活。现有的持久链接类型有两种:HTTP/1.0+的keep-alive和HTTP/1.1的persistent.性能

  • keep-alive测试

   先来看来keep-alive,先上图:spa

     这个是百度首页的一个HTTP事务,能够看到有个首部connection:keep-alive,这个就是第一种持久链接了。下面来看下这个持久链接是怎么创建的:代理

 

    这个就是请求的过程了:客户端先发出请求,以connection:keep-alive的形式传向服务器,若是服务器接受的请求的话响应中就会带有connection:keep- alive.事务

    当使用了connection:keep-alive时,可使用keep-alive首部传递一些关于持久链接的参数:timeout表示持续时间,max表示但愿还在这条持久链接上传输多少个HTTP服务,可是这些都不是承诺值,也就是说随时均可以反悔

    接下来讲说keep-alive持久链接须要注意的一些地方:

  1. 若是要是用持久链接,那么就必定要有正确的content-length这个描述主体长度的首部,由于持久链接会连续的传输HTTP事务,而判断连续的HTTP事 务之间的分界点就是靠content-length告诉的主体的长度了,若是错误或没有告诉主体的长度的话,那么就没办法知道这个事务在哪里结束了。

  2. 代理和网管必须再转发以前删除connection:keep-alive这个首部,这个涉及到哑代理问题,后面会说到。

  3. 由于持久链接能够随时关闭,因此必定要作好遇到当请求发出去响应还没回送回来的时候持久链接就断开的状况的准备,也就是有些时候可能要重新发送请求。

    哑代理和聪明的代理

    这里先说明下哑代理和聪明的代理的区别:哑代理只是单纯的转发请求,并不能进行解析处理、维持持久链接等其余工做,而聪明的代理能够解析接收到的报文同时能够维持持久链接。

     如上图,当客户端与服务器之间存在不解析直接转发的代理时,connection:keep-alive这个首部是直接转发给服务器的,服务器接收了这个请求以后,就会向客户端发送带有connection:keep-alive的响应,一样盲代理不会解析响应,直接将所有响应转发回客户端。由于客户端收到了这个首部,就认为创建持久链接已经成功了,可是中间的”笨代理“,并不知道这些事情,笨代理只有一种行为模式:在转发请求和回送服务器响应请求以后就认为此次事务结束了,等待链接断开,而这时因为connection:keep-alive首部已经发送到服务器和客户端,双方都认为持久链接已经创建完成,这样就变成了两边认为持久链接OK而中间的哑代理等待链接断开的状况,这种状况下若是客户端再一次在这条链接上发送请求,请求就会在亚代理处中止,由于哑代理已经在等待链接关闭。这种状态会致使浏览器一直处于挂起状态,直到客户端或服务器之中一个链接超时,关闭链接为止,一段美好的牵手就这么没了(哑代理就是把内容原封不动的转发到代理)。

    为了不这种状况,现代的代理是不会转发connection:keep-alive这个首部的。

    为了防止这个问题,网景提出了一个方案,采用插入Proxy-connection的方式,上图:

    来看看这个方案如何解决问题:

  1. 首先客户端发送Proxy-connection首部请求,这是一个非标准请求,也就是说即便服务器接收到这个首部也不知道他是干什么的,在服务器眼中它只知道客户端申请持久链接的首部为connection:keep-alive

  2. 哑代理的模式:报文来到了代理的位置,哑代理的话会直接转发请求不解析处理,则Proxy-connection这个首部直接被发给服务器,因为服务器不识别,因此直接忽略到这个首部,这样服务器在返回响应的时候便不会带有connection:keep-alive首部,当响应到达客户端的时候,客户端发现响应中没有connection:keep-alive首部,就认为服务器拒绝了持久链接的请求,也就是说客户端判断服务器是否接受持久链接请求还是靠响应是否存在connection首部来进行的。

  3. 聪明的代理的模式:聪明的代理会对请求进行解析,发现有 Proxy-connection这个首部的时候,便会把这个首部替换成connection:keep-alive,因为服务器只能识别connection首部,当它发现有这个首部的时候,就知道客户端进行了持久链接请求,就在响应中添加connection首部,回送给客户端。当客户端收到带有connection首部的响应时,便认为持久链接创建成功,而正好中间的聪明的路由也能够维持持久链接,这样整条链接就处于客户端OK代理OK服务器OK的状态,能够继续使用该持久链接进行报文发送。

    从上面所说的,我以为这个方案其实就是至关于对中间代理的类型进行了一次判断。

    可是这个方案只能解决中间只有一个代理的状况,若是聪明的任意一边还存在一个哑代理,那么仍会出现最开始的哑代理问题

  • persistent

    HTTP/1.1的持久链接默认是开启的,只有首部中包含connection:close,才会事务结束以后关闭链接。固然服务器和客户端仍能够随时关闭持久链接。

     当发送了connection:close首部以后客户端就没有办法在那条链接上发送更多的请求了。固然根据持久链接的特性,必定要传输正确的content-length。

     还有根据HTTP/1.1的特性,是不该该和HTTP/1.0客户端创建持久链接的。最后,必定要作好重发的准备。

     管道化链接

    HTTP/1.1容许在持久链接上使用管道,这样就不用等待前一个请求的响应,直接在管道上发送第二个请求,在高延迟下,提升性能。

      管道化链接的限制:

  • 不是持久链接就不能使用管道。

  • 必须按照一样的发送顺序回送响应,由于报文没有标签,极可能就顺序就乱咯。

  • 由于能够随时关闭持久链接,因此要随时作好重发准备

  • 不该该使用管道化发送重复发送会有反作用的请求(如post,重复提交)。

    就到这里了,画着好累。。。 

相关文章
相关标签/搜索