http2的真正性能到底如何

技术http2的真正性能到底如何http2的真正性能到底如何,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。一、研究目的http2的概念提出已经有相当长一

http2的真实表现如何?针对这个问题,本文详细介绍了相应的分析和解答,希望能帮助更多想要解决这个问题的小伙伴找到更简单易行的方法。

一、研究目的

http2的概念提出已经有相当长的时间了,网上也有很多关于http2的文章。但从搜索结果来看,现有的文章大多偏向于介绍http2,实际从数据上具体分析的很少。本文正是出于填补这一空白的目的,通过一系列的实验和数据分析,对http2的性能进行了深入的研究。当然,由于我的技能有限,实验中使用的方法必然有缺点。如果你发现什么问题,请问我,我会尽力修改和完善实验方法!

二、基础知识

关于HTTP2的基础知识,可以参考以下文章,这里不再赘述。

HTTP,HTTP2.0,SPDY,HTTPS,一些你应该知道的东西,

关于HTTP 2.0的那些事情

HTTP2.0的精彩日常生活

HTTP2特性和数据包捕获分析的一分钟预览

面向网络应用程序开发人员的HTTP/2

提高HTTP/2性能的7个技巧

通过学习相关资料,我们对HTTP2有了一个大致的了解。接下来,我们将设计一个模型来测试HTTP2的性能。

三、实验设计

设置实验组:设置一个HTTP2(SPDY)服务器,可以通过HTTP2响应请求。同时,可以定制响应的内容大小和响应的延迟时间。

设置控制组:设置一个HTTP1.x服务器,通过HTTP1.x响应请求,其可定制内容与实验组相同。此外,为了减少错误,HTTP1.x服务器使用https协议。

测试过程:客户端通过设置响应的内容大小、请求的资源数量、延迟时间、上下行带宽等参数,分别向实验组服务器和控制组服务器发送请求。并计算完成响应所需的时间。

由于从nginx切换到https 2需要升级nginx版本并获取https证书,服务器端各种自定义设置涉及的操作环节相对复杂,综合考虑,放弃了使用nginx作为实验服务器的方案,改为采用NodeJS方案。在实验的初始阶段,我们使用带有node-http2模块的原生NodeJS来构建服务器,之后我们使用带有node-spdy模块的express框架来构建服务器。原因是原生NodeJS对复杂请求的处理非常复杂,express框架对请求和响应做了一系列优化,可以有效减少人为错误。此外,node-http2模块与express框架不兼容,性能低于node-spdy模块(一般性能,node-spdy vs node-http2 # 98),而node-spdy模块的功能与node-http2模块基本相同。

1、服务器搭建

实验组和对照组的服务器逻辑完全一致,关键代码如下:

app.get('/option/?',(req,RES)={ allow(RES)letsize=req . query[' size ']let delay=req . query[' delay ']let buf=new buffer(size * 1024 * 1024)settimeout()={ RES . send(buf。

2、客户端搭建

客户端可以动态设置请求数量、资源数量、资源大小和服务器延迟时间。同时,借助Chrome的开发者工具,可以人工模拟不同的网络环境。完成对资源请求的响应后,将自动计算总运行时间。关键代码如下:

for(leti=0;ireqNum

 i++) {     $.get(url, function (data) {         imageLoadTime(output, pageStart)     }) }

客户端通过循环对资源进行多次请求,其数量可设置。每一次循环都会通过imageLoadTime更新时间,以实现时间统计的功能。

http2的真正性能到底如何

3、实验项目

a. http2性能研究

通过研究章节二的文章内容,可以把http2的性能影响因素归结于“延迟”和“请求数目”。本实验增加了“资源体积”和“网络环境”作为影响因素,下面将会针对这四项进行详细的测试实验。其中每一次实验都会重复10次,取平均值后作记录。

b. 服务端推送研究

http2还有一项非常特别的功能——服务端推送。服务端推送允许服务器主动向客户端推送资源。本实验也会针对这个功能展开研究,主要研究服务端推送的使用方法及其对性能的影响。

四、http2性能数据统计

1、延迟因素对性能的影响

http2的真正性能到底如何

   http2的真正性能到底如何

2、请求数目对性能的影响

通过上一个实验,可以知道在延迟为10ms的时候,http1.x和http2的时间统计相近,故本次实验延迟时间设置为10ms。

http2的真正性能到底如何

http2的真正性能到底如何

 http2的真正性能到底如何

 http2的真正性能到底如何

3、资源体积对性能的影响

通过上两个实验,可以知道在延迟为10ms,资源数目为30个的时候,http1.x和http2的时间统计相近,故本次实验延迟时间设置为10ms,资源数目30个。

http2的真正性能到底如何

http2的真正性能到底如何

4、网络环境对性能的影响

通过上两个实验,可以知道在延迟为10ms,资源数目为30个的时候,http1.x和http2的时间统计相近,故本次实验延迟时间设置为10ms,资源数目30个。

http2的真正性能到底如何

 http2的真正性能到底如何

五、http2服务端推送实验

本实验主要针对网络环境对服务端推送速度的影响进行研究。在本实验中,所请求/推送的资源都是一个体积为290Kb的JS文件。每一个网络环境下都会重复十次实验,取平均值后填入表格。

http2的真正性能到底如何

从上述表格可以发现一个非常奇怪的现象,在开启了网络节流以后(包括Wifi选项),服务端推送的速度都远远比不上普通的客户端请求,但是在关闭了网络节流后,服务端推送的速度优势非常明显。在网络节流的Wifi选项中,下载速度为30M/s,上传速度为15M/s。而测试所用网络的实际下载速度却只有542K/s,上传速度只有142K/s,远远达不到网络节流Wifi选项的速度。为了分析这个原因,我们需要理解“服务端推送”的原理,以及推送过来的资源的存放位置在哪里。

普通的客户端请求过程如下图:

http2的真正性能到底如何

服务端推送的过程如下图:

http2的真正性能到底如何

从上述原理图可以知道,服务端推送能把客户端所需要的资源伴随着index.html一起发送到客户端,省去了客户端重复请求的步骤。正因为没有发起请求,建立连接等操作,所以静态资源通过服务端推送的方式可以极大地提升速度。但是这里又有一个问题,这些被推送的资源又是存放在哪里呢?参考了这篇文章Issue  5: HTTP/2 Push以后,终于找到了原因。我们可以把服务端推送过程的原理图深入一下:

http2的真正性能到底如何

服务端推送过来的资源,会统一放在一个网络与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

若要使用服务端推送,则在服务端需要对响应的逻辑进行扩展,这个需要视情况具体分析实施。

下面附送实验所需源码:1、客户端页面

<!-- http1_vs_http2.html -->  <!DOCTYPE html> <html lang="en"> <head>    <meta charset="UTF-8">    <title>http1 vs http2</title>    <script src="//cdn.bootcss.com/jquery/1.9.1/jquery.min.js"></script>    <style>        .box {            float: left;            width: 200px;            margin-right: 100px;            margin-bottom: 50px;            padding: 20px;            border: 4px solid pink;            font-family: Microsoft Yahei;        }        .box h3 {            margin: 5px 0;        }        .box .done {            color: pink;            font-weight: bold;            font-size: 18px;        }        .box button {            padding: 10px;            display: block;            margin: 10px 0;        }    </style> </head> <body>    <div class="box">        <h3>Http1.x</h3>        <p>Time: <span id="output-http1"></span></p>        <p class="done done-1">&times; Unfinished...</p>        <button class="btn-1">Get Response</button>    </div>     <div class="box">        <h3>Http2</h3>        <p>Time: <span id="output-http2"></span></p>        <p class="done done-1">&times; Unfinished...</p>        <button class="btn-2">Get Response</button>    </div>     <div class="box">        <h3>Options</h3>        <p>Request Num: <input type="text" id="req-num"></p>        <p>Request Size (Mb): <input type="text" id="req-size"></p>        <p>Request Delay (ms): <input type="text" id="req-delay"></p>    </div>     <script>        function imageLoadTime(id, pageStart) {          let lapsed = Date.now() - pageStart;          document.getElementById(id).innerHTML = ((lapsed) / 1000).toFixed(2) + 's'        }                let boxes = document.querySelectorAll('.box')        let doneTip = document.querySelectorAll('.done')        let reqNumInput = document.querySelector('#req-num')        let reqSizeInput = document.querySelector('#req-size')        let reqDelayInput = document.querySelector('#req-delay')         let reqNum = 100        let reqSize = 0.1        let reqDelay = 300         reqNumInput.value = reqNum        reqSizeInput.value = reqSize        reqDelayInput.value = reqDelay         reqNumInput.onblur = function () {            reqNum = reqNumInput.value        }         reqSizeInput.onblur = function () {            reqSize = reqSizeInput.value        }         reqDelayInput.onblur = function () {            reqDelay = reqDelayInput.value        }         function clickEvents(index, url, output, server) {            doneTip[index].innerHTML = '&times; Unfinished...'            doneTip[index].style.color = 'pink'            boxes[index].style.borderColor = 'pink'            let pageStart = Date.now()            for (let i = 0; i < reqNum; i++) {                $.get(url, function (data) {                    console.log(server + ' data')                    imageLoadTime(output, pageStart)                    if (i === reqNum - 1) {                        doneTip[index].innerHTML = '&radic; Finished!'                        doneTip[index].style.color = 'lightgreen'                        boxes[index].style.borderColor = 'lightgreen'                    }                })            }        }         document.querySelector('.btn-1').onclick = function () {            clickEvents(0, 'https://localhost:1001/option?size=' + reqSize + '&delay=' + reqDelay, 'output-http1', 'http1.x')        }         document.querySelector('.btn-2').onclick = function () {            clickEvents(1, 'https://localhost:1002/option?size=' + reqSize + '&delay=' + reqDelay, 'output-http2', 'http2')        }    </script> </body> </html>

2、服务端代码(http1.x与http2仅有一处不同)

const http = require('https') // 若为http2则把'https'模块改为'spdy'模块 const url = require('url') const fs = require('fs') const express = require('express') const path = require('path')  const app = express()  const options = {   key: fs.readFileSync(`${__dirname}/server.key`),   cert: fs.readFileSync(`${__dirname}/server.crt`) }  const allow = (res) => {   res.header("Access-Control-Allow-Origin", "*")   res.header("Access-Control-Allow-Headers", "X-Requested-With")   res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS") }  app.set('views', path.join(__dirname, 'views')) app.set('view engine', 'ejs') app.use(express.static(path.join(__dirname, 'static')))  app.get('/option/?', (req, res) => {     allow(res)     let size = req.query['size']     let delay = req.query['delay']     let buf = new Buffer(size * 1024 * 1024)     setTimeout(() => {         res.send(buf.toString('utf8'))     }, delay) })  http.createServer(options, app).listen(1001, (err) => { // http2服务器端口为1002     if (err) throw new Error(err)     console.log('Http1.x server listening on port 1001.') })

关于http2的真正性能到底如何问题的解答就分享到这里了,希望

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/97011.html

(0)

相关推荐

  • arcsinx的不定积分,sinx的反函数的平方积分

    技术arcsinx的不定积分,sinx的反函数的平方积分sinx的反函数为arcsinx的不定积分:y=arcsinx或siny=x(x∈[-1,1])。arcsinx的平方的不定积分,写作:∫ arcsin²x dx分

    生活 2021年10月30日
  • 什么是分布式数据库和TIDB 整体架构

    技术什么是分布式数据库和TIDB 整体架构这篇文章给大家介绍什么是分布式数据库和TIDB 整体架构,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。TIDB 是一个分布式,强一致的可水平扩展的关系型数据

    攻略 2021年12月1日
  • Python语法举例分析

    技术Python语法举例分析这篇文章主要介绍“Python语法举例分析”,在日常操作中,相信很多人在Python语法举例分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Python语法举

    攻略 2021年11月20日
  • pkg安装包制作软件Packages for Mac是怎么样的

    技术pkg安装包制作软件Packages for Mac是怎么样的小编给大家分享一下pkg安装包制作软件Packages for Mac是怎么样的,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读

    攻略 2021年11月18日
  • Hutool Java工具类库_ExcelUtil怎么使用

    技术Hutool Java工具类库_ExcelUtil怎么使用这篇文章主要介绍“Hutool Java工具类库_ExcelUtil怎么使用”,在日常操作中,相信很多人在Hutool Java工具类库_ExcelUtil怎

    攻略 2021年11月29日
  • Go语言核心36讲,Go语言进阶技术二)--学习笔记

    技术Go语言核心36讲,Go语言进阶技术二)--学习笔记 Go语言核心36讲(Go语言进阶技术二)--学习笔记08 | container包中的那些容器
    我们在上次讨论了数组和切片,当我们提到数组的时候

    礼包 2021年10月20日