[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鏈接的管理。

相關文章
相關標籤/搜索