成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

深入研究:http2的真正性能到底如何

開發 前端
http2的概念提出已經有相當長一段時間了,而網上關于關于http2的文章也一搜一大把。但是從搜索的結果來看,現有的文章多是偏向于對http2的介紹,鮮有真正從數據上具體分析的。這篇文章正是出于填補這塊空缺內容的目的,通過一系列的實驗以及數據分析,對http2的性能進行深入研究。

[[174074]]

一、研究目的

http2的概念提出已經有相當長一段時間了,而網上關于關于http2的文章也一搜一大把。但是從搜索的結果來看,現有的文章多是偏向于對http2的介紹,鮮有真正從數據上具體分析的。這篇文章正是出于填補這塊空缺內容的目的,通過一系列的實驗以及數據分析,對http2的性能進行深入研究。當然,由于本人技術有限,實驗所使用的方法肯定會有不足之處,如果各位看官有發現問題,還請向我提出,我一定會努力修改完善實驗的方法的!

二、基礎知識

關于HTTP2的基礎知識,可以參考下列幾篇文章,在這里就不進行贅述了。

通過學習相關資料,我們已經對HTTP2有了一個大致的認識,接下來將通過設計一個模型,對HTTP2的性能進行實驗測試。

三、實驗設計

設置實驗組:搭建一個HTTP2(SPDY)服務器,能夠以HTTP2的方式響應請求。同時,響應的內容大小,響應的延遲時間均可自定義。

設置對照組:搭建一個HTTP1.x服務器,以HTTP1.x的方式響應請求,其可自定義內容同實驗組。另外為了減少誤差,HTTP1.x服務器使用https協議。

測試過程:客戶端通過設置響應的內容大小、請求資源的數量、延遲時間、上下行帶寬等參數,分別對實驗組服務器和對照組服務器發起請求,統計響應完成所需時間。

由于nginx切換成http2需要升級nginx版本以及取得https證書,且在服務器端的多種自定義設置所涉及的操作環節相對復雜,綜合考慮之下放棄使用nginx作為實驗用服務器的方案,而是采用了NodeJS方案。在實驗的初始階段,使用了原生的NodeJS搭配node-http2模塊進行服務器搭建,后來改為了使用express框架搭配node-spdy模塊搭建。原因是,原生NodeJS對于復雜請求的處理非常復雜,express框架對請求、響應等已經做了一系列的優化,可以有效減少人為的誤差。另外node-http2模塊無法與express框架兼容,同時它的性能較之node-spdy模塊也更低(General performance, node-spdy vs node-http2 #98),而node-spdy模塊的功能與node-http2模塊基本一致。

1、服務器搭建

實驗組和對照組的服務器邏輯完全一致,關鍵代碼如下:

  1. app.get('/option/?', (req, res) => { 
  2.     allow(res) 
  3.     let size = req.query['size'
  4.     let delay = req.query['delay'
  5.     let buf = new Buffer(size * 1024 * 1024) 
  6.     setTimeout(() => { 
  7.         res.send(buf.toString('utf8')) 
  8.     }, delay) 
  9. })  

其邏輯是,根據從客戶端傳入的參數,動態設置響應資源的大小和延遲時間。

2、客戶端搭建

客戶端可動態設置請求的次數、資源的數目、資源的大小和服務器延遲時間。同時搭配Chrome的開發者工具,可以人為模擬不同網絡環境。在資源請求響應結束后,會自動計算總耗時時間。關鍵代碼如下:

  1. for (let i = 0; i < reqNum; i++) { 
  2.     $.get(url, function (data) { 
  3.         imageLoadTime(output, pageStart) 
  4.     }) 
  5.  

客戶端通過循環對資源進行多次請求,其數量可設置。每一次循環都會通過imageLoadTime更新時間,以實現時間統計的功能。

3、實驗項目

a. http2性能研究

通過研究章節二的文章內容,可以把http2的性能影響因素歸結于“延遲”和“請求數目”。本實驗增加了“資源體積”和“網絡環境”作為影響因素,下面將會針對這四項進行詳細的測試實驗。其中每一次實驗都會重復10次,取平均值后作記錄。

b. 服務端推送研究

http2還有一項非常特別的功能——服務端推送。服務端推送允許服務器主動向客戶端推送資源。本實驗也會針對這個功能展開研究,主要研究服務端推送的使用方法及其對性能的影響。

四、http2性能數據統計

1、延遲因素對性能的影響

 

   

2、請求數目對性能的影響

通過上一個實驗,可以知道在延遲為10ms的時候,http1.x和http2的時間統計相近,故本次實驗延遲時間設置為10ms。

 

 

 

3、資源體積對性能的影響

通過上兩個實驗,可以知道在延遲為10ms,資源數目為30個的時候,http1.x和http2的時間統計相近,故本次實驗延遲時間設置為10ms,資源數目30個。

 

4、網絡環境對性能的影響

通過上兩個實驗,可以知道在延遲為10ms,資源數目為30個的時候,http1.x和http2的時間統計相近,故本次實驗延遲時間設置為10ms,資源數目30個。

 

 

五、http2服務端推送實驗

本實驗主要針對網絡環境對服務端推送速度的影響進行研究。在本實驗中,所請求/推送的資源都是一個體積為290Kb的JS文件。每一個網絡環境下都會重復十次實驗,取平均值后填入表格。

 

從上述表格可以發現一個非常奇怪的現象,在開啟了網絡節流以后(包括Wifi選項),服務端推送的速度都遠遠比不上普通的客戶端請求,但是在關閉了網絡節流后,服務端推送的速度優勢非常明顯。在網絡節流的Wifi選項中,下載速度為30M/s,上傳速度為15M/s。而測試所用網絡的實際下載速度卻只有542K/s,上傳速度只有142K/s,遠遠達不到網絡節流Wifi選項的速度。為了分析這個原因,我們需要理解“服務端推送”的原理,以及推送過來的資源的存放位置在哪里。

普通的客戶端請求過程如下圖:

服務端推送的過程如下圖:

從上述原理圖可以知道,服務端推送能把客戶端所需要的資源伴隨著index.html一起發送到客戶端,省去了客戶端重復請求的步驟。正因為沒有發起請求,建立連接等操作,所以靜態資源通過服務端推送的方式可以極大地提升速度。但是這里又有一個問題,這些被推送的資源又是存放在哪里呢?參考了這篇文章Issue 5: HTTP/2 Push以后,終于找到了原因。我們可以把服務端推送過程的原理圖深入一下:

服務端推送過來的資源,會統一放在一個網絡與http緩存之間的一個地方,在這里可以理解為“本地”。當客戶端把index.html解析完以后,會向本地請求這個資源。由于資源已經本地化,所以這個請求的速度非常快,這也是服務端推送性能優勢的體現之一。當然,這個已經本地化的資源會返回200狀態碼,而非類似localStorage的304或者200 (from cache)狀態碼。Chrome的網絡節流工具,會在任何“網絡請求”之間加入節流,由于服務端推送活來的靜態資源也是返回200狀態碼,所以Chrome會把它當作網絡請求來處理,于是導致了上述實驗所看到的問題。

六、研究結論

通過上述一系列的實驗,我們可以知道http2的性能優勢集中體現在“多路復用”和“服務端推送”上。對于請求數目較少(約小于30個)的情況下,http1.x和http2的性能差異不大,在請求數目較多且延遲大于30ms的情況下,才能體現http2的性能優勢。對于網絡狀況較差的環境,http2的性能也高于http1.x。與此同時,如果把靜態資源都通過服務端推送的方式來處理,加載速度會得到更加巨大的提升。

在實際的應用中,由于http2多路復用的優勢,前端應用團隊無須采取把多個文件合并成一個,生成雪碧圖之類的方法減少網絡請求。除此之外,http2對于前端開發的影響并不大。

服務端升級http2,如果是使用NodeJS方案,只需要把node-http模塊升級為node-spdy模塊,并加入證書即可。nginx方案的話可以參考這篇文章:Open Source NGINX 1.9.5 Released with HTTP/2 Support

若要使用服務端推送,則在服務端需要對響應的邏輯進行擴展,這個需要視情況具體分析實施。

七、后記

紙上得來終覺淺,絕知此事要躬行。如果不是真正的設計實驗、進行實驗,我可能根本不會知道原來http2也有坑,原來使用Chrome做調試的時候也有需要注意的地方。

希望這篇文章能夠對研究http2的同學有些許幫助吧,如文章開頭所說,如果你發現我的實驗設計有任何問題,或者你想到了更好的實驗方式,也歡迎向我提出,我一定會認真研讀你的建議的!

下面附送實驗所需源碼:1、客戶端頁面

  1. <!-- http1_vs_http2.html --> 
  2.  
  3. <!DOCTYPE html> 
  4. <html lang="en"
  5. <head> 
  6.    <meta charset="UTF-8"
  7.    <title>http1 vs http2</title> 
  8.    <script src="//cdn.bootcss.com/jquery/1.9.1/jquery.min.js"></script> 
  9.    <style> 
  10.        .box { 
  11.            floatleft
  12.            width: 200px; 
  13.            margin-right: 100px; 
  14.            margin-bottom: 50px; 
  15.            padding: 20px; 
  16.            border: 4px solid pink; 
  17.            font-family: Microsoft Yahei; 
  18.        } 
  19.        .box h2 { 
  20.            margin: 5px 0; 
  21.        } 
  22.        .box .done { 
  23.            color: pink; 
  24.            font-weight: bold; 
  25.            font-size: 18px; 
  26.        } 
  27.        .box button { 
  28.            padding: 10px; 
  29.            display: block; 
  30.            margin: 10px 0; 
  31.        } 
  32.    </style> 
  33. </head> 
  34. <body> 
  35.    <div class="box"
  36.        <h2>Http1.x</h2> 
  37.        <p>Time: <span id="output-http1"></span></p> 
  38.        <p class="done done-1">× Unfinished...</p> 
  39.        <button class="btn-1">Get Response</button> 
  40.    </div> 
  41.  
  42.    <div class="box"
  43.        <h2>Http2</h2> 
  44.        <p>Time: <span id="output-http2"></span></p> 
  45.        <p class="done done-1">× Unfinished...</p> 
  46.        <button class="btn-2">Get Response</button> 
  47.    </div> 
  48.  
  49.    <div class="box"
  50.        <h2>Options</h2> 
  51.        <p>Request Num: <input type="text" id="req-num"></p> 
  52.        <p>Request Size (Mb): <input type="text" id="req-size"></p> 
  53.        <p>Request Delay (ms): <input type="text" id="req-delay"></p> 
  54.    </div> 
  55.  
  56.    <script> 
  57.        function imageLoadTime(id, pageStart) { 
  58.          let lapsed = Date.now() - pageStart; 
  59.          document.getElementById(id).innerHTML = ((lapsed) / 1000).toFixed(2) + 's' 
  60.        } 
  61.         
  62.        let boxes = document.querySelectorAll('.box'
  63.        let doneTip = document.querySelectorAll('.done'
  64.        let reqNumInput = document.querySelector('#req-num'
  65.        let reqSizeInput = document.querySelector('#req-size'
  66.        let reqDelayInput = document.querySelector('#req-delay'
  67.  
  68.        let reqNum = 100 
  69.        let reqSize = 0.1 
  70.        let reqDelay = 300 
  71.  
  72.        reqNumInput.value = reqNum 
  73.        reqSizeInput.value = reqSize 
  74.        reqDelayInput.value = reqDelay 
  75.  
  76.        reqNumInput.onblur = function () { 
  77.            reqNum = reqNumInput.value 
  78.        } 
  79.  
  80.        reqSizeInput.onblur = function () { 
  81.            reqSize = reqSizeInput.value 
  82.        } 
  83.  
  84.        reqDelayInput.onblur = function () { 
  85.            reqDelay = reqDelayInput.value 
  86.        } 
  87.  
  88.        function clickEvents(index, url, output, server) { 
  89.            doneTip[index].innerHTML = '× Unfinished...' 
  90.            doneTip[index].style.color = 'pink' 
  91.            boxes[index].style.borderColor = 'pink' 
  92.            let pageStart = Date.now() 
  93.            for (let i = 0; i < reqNum; i++) { 
  94.                $.get(url, function (data) { 
  95.                    console.log(server + ' data'
  96.                    imageLoadTime(output, pageStart) 
  97.                    if (i === reqNum - 1) { 
  98.                        doneTip[index].innerHTML = '√ Finished!' 
  99.                        doneTip[index].style.color = 'lightgreen' 
  100.                        boxes[index].style.borderColor = 'lightgreen' 
  101.                    } 
  102.                }) 
  103.            } 
  104.        } 
  105.  
  106.        document.querySelector('.btn-1').onclick = function () { 
  107.            clickEvents(0, 'https://localhost:1001/option?size=' + reqSize + '&delay=' + reqDelay, 'output-http1''http1.x'
  108.        } 
  109.  
  110.        document.querySelector('.btn-2').onclick = function () { 
  111.            clickEvents(1, 'https://localhost:1002/option?size=' + reqSize + '&delay=' + reqDelay, 'output-http2''http2'
  112.        } 
  113.    </script> 
  114. </body> 
  115. </html>  

2、服務端代碼(http1.x與http2僅有一處不同)

  1. const http = require('https') // 若為http2則把'https'模塊改為'spdy'模塊 
  2. const url = require('url'
  3. const fs = require('fs'
  4. const express = require('express'
  5. const path = require('path'
  6.  
  7. const app = express() 
  8.  
  9. const options = { 
  10.   key: fs.readFileSync(`${__dirname}/server.key`), 
  11.   cert: fs.readFileSync(`${__dirname}/server.crt`) 
  12.  
  13. const allow = (res) => { 
  14.   res.header("Access-Control-Allow-Origin""*"
  15.   res.header("Access-Control-Allow-Headers""X-Requested-With"
  16.   res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS"
  17.  
  18. app.set('views', path.join(__dirname, 'views')) 
  19. app.set('view engine''ejs'
  20. app.use(express.static(path.join(__dirname, 'static'))) 
  21.  
  22. app.get('/option/?', (req, res) => { 
  23.     allow(res) 
  24.     let size = req.query['size'
  25.     let delay = req.query['delay'
  26.     let buf = new Buffer(size * 1024 * 1024) 
  27.     setTimeout(() => { 
  28.         res.send(buf.toString('utf8')) 
  29.     }, delay) 
  30. }) 
  31.  
  32. http.createServer(options, app).listen(1001, (err) => { // http2服務器端口為1002 
  33.     if (err) throw new Error(err) 
  34.     console.log('Http1.x server listening on port 1001.'
  35. })  
責任編輯:龐桂玉 來源: segmentfault
相關推薦

2022-07-27 14:24:38

MySQL數據庫SQL

2011-12-15 10:43:20

JavaNIO

2012-10-29 10:30:36

CSSWeb前端display

2010-08-03 17:36:55

DB2數據庫

2011-06-01 10:58:54

Android Service

2022-05-11 09:03:05

CSS容器文本換行

2015-08-19 11:17:02

Windows 10DirectX 12

2010-08-26 15:48:21

DB2優化數據庫

2010-06-21 13:07:14

2010-05-31 17:45:50

MySQL行鎖

2016-01-12 18:04:55

Java異常研究

2017-06-06 11:29:23

Java異常研究與分析

2018-12-24 15:00:58

混合云多云云采用

2010-11-23 16:35:59

MySQL刪除多表數據

2010-11-18 17:24:27

Oracle旋轉ins

2021-05-25 09:00:00

Kubernetes容器集群

2009-12-08 18:45:17

PHP檢查函數可用

2013-01-07 13:38:56

Android開發布局長度單位

2010-05-19 14:45:46

2022-04-19 08:28:34

main函數
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品欧美一区二区 | www.99热.com | 国产1区在线 | 久久人人爽人人爽人人片av免费 | 另类 综合 日韩 欧美 亚洲 | 国产成人精品综合 | 国产9 9在线 | 中文 | 欧美一级淫片007 | aaaaa毛片| 天天碰日日操 | 国产精品久久久久久久久久 | 国产中文字幕网 | 日韩欧美中文字幕在线观看 | 在线观看黄色大片 | 黄视频免费观看 | 亚洲男女视频在线观看 | 欧美中文在线 | 国产综合一区二区 | 91香蕉视频在线观看 | 91伊人| 91久久精品日日躁夜夜躁欧美 | 色婷婷综合在线观看 | 久久久久亚洲 | 老头搡老女人毛片视频在线看 | 精品国产区| 国产在线精品区 | 精品久久久久久国产 | 欧美中文一区 | 成人精品 | 欧美亚洲高清 | 特黄视频| 日本视频一区二区三区 | 亚洲综合成人网 | 黄色片av | 亚洲精品成人 | 久久免费看 | 国产成人免费 | 干干干日日日 | 国产一级视频在线 | 精品久久久999 | 91精品国产综合久久精品图片 |