緣起:node
產品業務上有個類數據庫服務的請求時間比較長(相似mysql的sql查詢),爲了優化減小併發時的請求數,作了一個併發時共用請求的優化。mysql
經過單元測試後,想經過手動模擬看下效果,發現優化一直不能生效。sql
定位問題:chrome
一、在mac下,同時開了兩個chrome窗口,分別促發訪問同一個接口(請求入口打印input,中間設定幾秒的延時,出口打印output)。數據庫
async test(ctx) { console.log('input'); await bluebird.delay(10000); console.log('output'); ctx.response.body = 'ok'; }
輸出結果以下:瀏覽器
input
output
input
output
結果分析:兩次請求沒法併發執行,而是串行到一塊兒,當第一個請求返回後,第二個請求才開始進入執行。併發
猜想:是不是在用的egg.js框架,給作的這種特性?爲了方便調試環境的代碼測試?但是以前看egg.js的代碼也沒看到這個功能呀?文檔也沒說明這個功能呀?框架
二、同事提出了疑惑「不多是egg.js的實現,否則其它的框架難道都得實現一套」?koa
三、一樣代碼,用production模式執行下(若是能夠串行,那麼生產環境是不可能這麼處理的)。async
結果保持不變:
input
output
input
output
一樣的代碼,換koa框架進行測試。
一樣的代碼,換node原生http服務進行測試。
結果保持不變:
input
output
input
output
結果分析:終結了測試1中的猜測。只能是node或如下的實現。
四、測試下不一樣機器的瀏覽器同時訪問。
結果爲能併發成功:
input
input
output
output
測試了同一機器的不一樣類型的瀏覽器進行測試(用了chrome和safari)。
結果爲能併發成功:
input
input
output
output
結果分析:chrome 兩個窗口訪問請求並非獨立的。
猜想:chrome兩個窗口相同的請求共用了tcp鏈接。(纔想到http1.1的服用tcp請求的時候是按順序的)。
五、打印出tcp鏈接對應的請求端的端口。
當在mac下兩個chrome窗口的時候,
結果爲:
input 54345 output 54345 input 54345 output 54345
當不一樣瀏覽器的請求的接口:
結果爲:
input 54355 input 54356 output 54355 output 54356
結果分析:在純chrome環境下,相同http請求共用了tcp鏈接,產生串行的效果。在區分瀏覽器的環境下,兩個http請求分別使用了各自的tcp鏈接,能產生併發效果。
結論:在chrome瀏覽器,即便你開了兩個窗口,可是它們仍是不徹底獨立的,會共用tcp鏈接。產生請求串行效果。必定狀況下方便調試。
若是要測試併發的http請求。須要開啓多個tcp鏈接。