[skill][http] http管道化链接

 

已知http的请求响应是一对一的. 就是一个请求跟着接下来的响应即是与之配对了.ios

而另外一种方式, 能够依靠顺序, 即发送多个http请求, 而后返回对个http响应. 严格按照顺序将他们对应起来, 称为管道化连接.git

 

可是因为有不少问题, 支持的都很差. 实际应用应该也是比较少的.github

 

转发一篇以下:浏览器

原文地址: http://www.yanglicalm.com/2017/02/12/%E7%AE%A1%E9%81%93%E5%8C%96%E8%BF%9E%E6%8E%A5/安全

 

其实一切都是由管道化链接而起,这是一个比较有意思的链接方式。性能优化

HTTP/1.1 容许在持久链接上可选的使用请求管道。这是相对于keep-alive链接的又一性能优化。在相应到达以前,能够将多条请求放入队列,当第一条请求发往服务器的时候,第二第三条请求也能够开始发送了,在高延时网络条件下,这样作能够下降网络的环回时间,提升性能。服务器


如上图所示,展现了管线化链接的机制,可是也有几点限制:网络

  • 若是客户端没法确认链接是持久的,就不该该使用管道
  • 必须按照与请求相同的顺序回送HTTP响应,由于HTTP报文中是没有序列号的,因此若是收到的响应失序了,就没办法将其与请求匹配起来
  • HTTP客户端必须作好链接会在任意时刻关闭的准备,还要准备好重发全部未完成的管道化请求
  • HTTP客户端不该该用管道化的方式发送回产生反作用的请求,好比POST请求。

管线化在iOS中的应用

WWDC 2012 session 706 - Networking Best Practices中,Apple的工程师介绍了管线化的概念,咱们知道了在NSMutableRequest有个属性叫作HTTPShouldUsePipelining,标示是否开启管线化链接,可是奇怪的是,这个值默认是NO,按说如此强势的功能为何要设置为NO呢,下面咱们来看看。session

经过上面的介绍咱们会发现,客户端接收响应的顺序必须和发出的请求顺序相同,也就是说这依赖于服务器对于相应的排序,那么问题来了,若是服务器不支持管线化的话,那么响应就会乱序,形成意想不到的问题,有几个很出名的bug:app

  • Safari开发团队接到多起报告,说是网页上展现的图片内容混乱,后来通过排查发现是当时的Safari版本默认开启管线化链接,可是不少站点的服务器并不支持,致使这个bug,随即Safari团队宣布不在默认开启管线化链接,事件详情在这里
  • AFNetworking曾经也默认开启管线化链接,后来接到一个issue,也是用户下载多张图片,后来发现图片的内容混淆了,具体内容点这里

可是有件事情是很让我困惑的,我在阅读SDWebImage源码的时候,在SDWebImageDownloader类中将HTTPShouldUsePipelining设置为了YES,不知道为何没有问题,但愿有了解的大神能够给个解答。

除了上述的问题以外,管线化链接仍是有性能问题的:

  • 这篇文章从安全角度指出了管线化链接的问题,而且谈到了一些特定状况下的性能损失。
  • 这篇文章测试了几个主流的浏览器,给出了管线化链接的性能并非一直都是取胜的。
  • WWDC 2015 - Networking with NSURLSession详细解释了一种叫作Head of line blocking的问题,是管线化链接的巨大瓶颈

Head of line blocking

来解释下这个概念,翻译成中文是线头阻塞。咱们知道,管线化是把多个HTTP请求放到一个TCP链接中一一发送,而在发送过程当中不须要等待服务器对前一个请求的响应,只不过,客户端仍是要按照发送请求的顺序来接收响应,也就是说,若是第一个请求耗费了服务器不少的处理时间,那么后面的请求都要等待第一个处理完,也就出现了线头阻塞。

目前,直到HTTP/1.0都没有好的方法来解决这个问题,将来的HTTP/2.0或者SPDY中的异步操做才能解决这个问题

以上三篇,是关于HTTP链接的管理。