当前位置: 首页 > news >正文

大家都在用HTTP/2了,而你还没听说过?

自2013年HTTP/2推出以来,HTTP/2已经得到了长足发展,浏览器平台基本提供了HTTP/2的支持,知乎,豆瓣等国内大型平台也已经部分切换到HTTP/2了。

HTTP/2优点

多路复用请求 对请求划分优先级 压缩HTTP头 服务器推送流

HTTP/2支持情况:

chrome,firefox,ie11(win10版)都已经支持

详情可查看:caniuse.com/#search=htt…

HTTP/2缓存情况:

HTTP/2并不像我们所在网上搜索到的那样不能缓存,只是需要在服务器端配置缓存,如:"expires":"Tue, 09 Oct 2018 11:27:20 GMT"。

测试方法:

在地图中应用时,加载图片有两种方式,一种是直接在img实例上设置url,让浏览器自己去触发访问图片,另一种是通过ajax加载(xhr.responseType = 'blob';,因为ajax请求过来的都是二进制字符串,所以要解析,后端读取文件和返回文件内容时同样要设置参数为binary),请求的结果通过img.src = window.URL.createObjectURL(data);解析成图片url。

根据两种加载方式,我构造了四组测试代码,并分别选取了每个图片大小为237KB和2KB的大小两组图片进行测试:

  1. HTTP/2&&AJAX加载
  2. HTTP/2&&浏览器加载
  3. http1.1&&AJAX加载
  4. http1.1&&浏览器加载

其它注意事项

使用浏览器访问的时候一定要用https协议访问,http协议访问不到

chrome允许本地https,进入chrome://flags/#allow-insecure-localhost设置其值为enabled

chrome里network内列标题上右键可打开protocol列查看请求的协议是不是h2

初次加载时会自动加载favicon.ico文件,可能会导致出错

代码实现

localhost-cert.pem

-----BEGIN CERTIFICATE-----
MIIC+zCCAeOgAwIBAgIJALUOjGkvsHSZMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV
BAMMCWxvY2FsaG9zdDAeFw0xODAxMjUwNTMxMDFaFw0xODAyMjQwNTMxMDFaMBQx
EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBANRicexesNtTbjVnxKyEWalFovZUEYQ/FRjArJAndaEBSVlsrTRFrp3nEUNx
6O6EUM4SrfOTCfEW6Pi9YqH8wVk8/G3BCOG99as6GIHabkbC79UiNdDhAQLr10+g
gaXl+QYxvGEvk/Qb/9LRFc3EqurVNmKdEPVUUpgcR8dL9SnOguLoSuKA2U+5AYLm
lX0lUG2S34o+H+Ck6dC8IK94uFNpyNPvd4xf+xEERBm7Q5IVLjZ0D40luF1g7S9L
IltT8BTYeYeCWGoNifQccS/5qfwuK3C7ga29lduJKNmDzhiKCCTelU92+COYisiE
sgYK4fbFnGHbiETFu87IJsABD2kCAwEAAaNQME4wHQYDVR0OBBYEFOtVzO6eutPf
g85CvFu8q7fA5EzxMB8GA1UdIwQYMBaAFOtVzO6eutPfg85CvFu8q7fA5EzxMAwG
A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFC+aeqkhe0YugcIP4cVCpPI
6xcfG0IZ82I94DhejVmsio2zP3kekR7ekzY4z28d6Kz03X0j+ll71xxZKZljnl3K
4C7oiBzj8ypCykXj03JDWNQ3sZNycfF/53OOk5Gu18qQ77TjqDpOGKU0xL45SmoB
oH/X2e9ccygMKOAAKqjT4ZVxksShC+tE+ij8ocBRfkMnJw0mfNAPlSjYw/Ho6WLJ
qlz0KyY5LkVHJbznXbN6S1K2FujJdyf7CkxMSb2bilDk8YvtXp8wFZg2R7Phi+dt
gbEx47N2hM0tLF0yPjAyBa+JKC2rG+/AS5ZfcTjYG3o+M84Y6l6QL3AXacn5L0k=
-----END CERTIFICATE-----

复制代码

localhost-privkey.pem

-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDUYnHsXrDbU241
Z8SshFmpRaL2VBGEPxUYwKyQJ3WhAUlZbK00Ra6d5xFDcejuhFDOEq3zkwnxFuj4
vWKh/MFZPPxtwQjhvfWrOhiB2m5Gwu/VIjXQ4QEC69dPoIGl5fkGMbxhL5P0G//S
0RXNxKrq1TZinRD1VFKYHEfHS/UpzoLi6ErigNlPuQGC5pV9JVBtkt+KPh/gpOnQ
vCCveLhTacjT73eMX/sRBEQZu0OSFS42dA+NJbhdYO0vSyJbU/AU2HmHglhqDYn0
HHEv+an8Litwu4GtvZXbiSjZg84Yiggk3pVPdvgjmIrIhLIGCuH2xZxh24hExbvO
yCbAAQ9pAgMBAAECggEANdwxX+wzlat2y3xhWA7IXjEWvrlbJ9qHkxtpp7UaE5ar
702sLxFs0waCTkRY+gP8KgZ6rsafQtC4jDwbA1GCBwt8SKkng3gVETNOe7/VL4TI
JZjjZPFqvD7q/3qI5nWHzZZXW54hO0rOebwkd2ZkoeEoRaHnZw/XUlP5sAUHS25p
LcmLcsY3j4vNG3px2K6yucfQwjidV0wSkh+xx5BXTwN65E3uwhBlu8DuV1G/Rv/H
/jXtX3FtF5tqGI/n4RtXGFmfv/ObbdICSxKFoprfv+fQaCk8NDm0uUadPHEOg5Yt
nTu6+52PEneo1dKR++1YVjHQGXqeW3xyuxuJEj6xwQKBgQD36qqkJ4Fo8+HhA1Ia
mKjt53ZItgRb1ecCIckWKG321ohCsVQB4GcNoN75dLt5uHtulcV4RjjK+mUJvQpD
iMnKdXcoJNzfdz0zqqeMH6grCs5FRqkj7UNhqtuSm9z/sQNjpcnE8gUOoA1hGQlA
JYIDcpTv0FkJGF72pyA+Q6Z05QKBgQDbTzIcWAW/wAg42K24hLtM4/hSaGHxovbt
7x1e0ymUVfXja3tvgrR6ptEI9jP+8tCJn9n4+TBifwKEMZdOU1JicFvVNjvRCEtg
INdm/Le8gzfYnCcfv0b9P1of9ZdbjHuYbe6sJZ2dm1h3auqojO/R1M7MT0vJkaYy
ZpbG8O2sNQKBgQCHCkoc1HAHLSESoe5tEk6iF/w0KwFAzMjiPmj8KtWLKNxcB5+M
ziEUKVaLZuxfpv+FAwvnMcjpt26l2VTn6HCSWV2ofjvZdWfe5swQ5YWCvIYS8iRb
r3eOkbS8rS26ET+ZXcsD/hiHGONwymRhjoy9OAKshj6ZV68Sh4JmqA7ZiQKBgFnQ
3VzuT6xwIO3nD356HZsn4hMd3L7xVt+rBgRHxseRTNqOskbA6NkyaHmbG0BWgUFb
zhFBPKeaDJXHGYhiZ2MZUQLI60Z4dyYvTQhIh5cUxlJX4U4HMDOXNnnQQuSjbBrJ
Ku4lmZ9qd5iwmNnennj5Bph2ATvUApSxnx5qnWvhAoGAPKLPKCuVoJS6FUZXl4ef
Pm0JYq+vl301wFAs9+4sf9kB3gA+xRFt8XHOmhaCgTDTea/EvSCR4FDO1BZgKpre
iyeQ5YdPYJ7sVq0TgQLCMzyqopG2f2/mmnJ/jzZhOp2C+gtqO0sKko6MZZTBEs3G
M94dSazKORHbqv9K6v49nls=
-----END PRIVATE KEY-----

复制代码

index.js

const http2 = require('http2');
const fs = require('fs');

const server = http2.createSecureServer({
  key: fs.readFileSync('localhost-privkey.pem'),
  cert: fs.readFileSync('localhost-cert.pem')
});
server.on('error', (err) => console.error(err));
server.on('socketError', (err) => console.error(err));

server.on('request', (request, response) => {
    console.log('./images'+request.url);
    
    //格式必须为 binary 否则会出错'./images'+request.url
    var content =  fs.readFileSync('./images'+request.url,"binary");   
    response.writeHead(200, {
        "Content-Type": "image/png",
        "expires":"Tue, 09 Oct 2018 11:27:20 GMT",
        "Access-Control-Allow-Origin": "http://localhost:8080"
    });
    response.write(content,"binary"); //格式必须为 binary,否则会出错
    response.end();
});

server.listen(8443);
复制代码

index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>HTTP/2测试</title>
        <script src="./http.js"></script>
    </head>
    <body>
123
<div id="imgContainer"></div>
    </body>
    <script>
        for(var i=1; i<16; i++){
            // GET('https://localhost:8443/'+i+'.png',function(response){
            //     drawImg(response);
            // });

            // GET('http://localhost:8080/http2test/images/'+i+'.png',function(response){
            //     drawImg(response);
            // });

            // var myImage = new Image();
            // myImage.src = 'https://localhost:8443/'+i+'.png';
            // document.body.appendChild(myImage);

            var myImage = new Image();
            myImage.src = 'http://localhost:8080/http2test/images/'+i+'.png';
            document.body.appendChild(myImage);

            
        }


        function drawImg(data){
            var img = new Image();
            img.src = window.URL.createObjectURL(data);
            img.onload = function(){
                window.URL.revokeObjectURL(img.src);
            }
            document.body.appendChild(img);
        }
        
    </script>
</html>
复制代码

http.js

/**
 * 发起异步请求的库
 */

 function GET(url,callback){
    var xhr = new XMLHttpRequest();
    xhr.open('GET',url,true);
    xhr.responseType = 'blob';
    xhr.onload = function(){
        if(xhr.readyState === 4 && xhr.status >= 200 && xhr.status <300 && xhr.response){
            callback(xhr.response);
        }
    }
    xhr.send();
 }
复制代码

rename.js(用于快速生成大量不同名的相同文件)

const fs = require('fs');


var path = './images';
var dirs = fs.readdirSync(path);
var n = 0;
for(let i in dirs){
    var filename = dirs[i].split('.');
    var type = filename[filename.length-1];
    if(type=='png'){
        fs.renameSync(path+'/'+dirs[i],path+'/'+n+'.png');
        n +=1;
    }else{
        fs.unlinkSync(path+'/'+dirs[i]);
    }
    console.log('处理完成:'+dirs[i]);
}
复制代码

完整代码地址: 可以直接跑起来的http/2与http/1.1的对比测试

测试结果:

因为本地加载实在太快,为尽量模拟生产环境网络情况,以下测试都是使用Chrome的fast3G模式。

类型 请求方式大(237kb)小(2kb)文件文件数加载时间
HTTP/2浏览器加载402.81s
HTTP/1.1浏览器加载405.89s
HTTP/2AJAX402.49s
HTTP/1.1AJAX405.82s
HTTP/2浏览器加载4052.59s
HTTP/1.1浏览器加载4052.57s
HTTP/2AJAX4052.66s
HTTP/1.1AJAX4052.58s

由此可见: _HTTP/2的优势主要体现在大量小图片的加载上,对于少量大图片的加载并不占太大优势,并且,网络条件如果非常好的时候,由于加载非常快,HTTP/2也不能体现出优势。

HTTP/2在WebGIS等地图应用上的设想:

WebGIS以瓦片技术得以普及,瓦片即请求和文件,每加载一个瓦片都需要请求一次服务器上的图片或其它格式的文件。地图瓦片大多为40kb左右的png文件,且一次加载数量都在20左右。由于http1.1本身的限制,浏览器只能同时加载6个文件(不同的浏览器策略额细微的差别),当地图浏览窗口移动时,前端会同时发送大量AJAX请求来加载瓦片。 此时浏览器就会受到阻塞,需要先等待队列前面的文件加载完成才能加载后面的文件。

HTTP/2的并发特性正好能解决此问题,也正好能对应这种场景。

高德地图部分使用了HTTP/2, 谷歌地图全部使用了HTTP/2 百度地图还没有使用HTTP/2 mapbox没有使用HTTP/2

目前唯一的问题是需要统计ie11的市场占用率,若占用率还是太高切换之后处理起来是个麻烦事。

参考:

Node.js中HTTP/2的使用:nodejs.org/api/http2.h…

PHP中HTTP/2深入分析:www.phpchina.com/article-402…

相关文章:

  • ➹使用webpack配置多页面应用(MPA)
  • Linux服务器配置---ntp
  • 基于NetCore C#的在线代码生成器
  • CSS3 动画卡顿解决方案
  • ywy_c_asm题
  • Vue源码解析(二)Vue的双向绑定讲解及实现
  • CF960G Bandit Blues(第一类斯特林数)
  • 我的网站搭建 (第21天) 评论功能设计
  • PHP 5.6 已结束安全支持,你升级到 PHP 7 系列了吗?
  • 企业网管用linux搭建邮件服务器为公司降本增效
  • Android基础:常见布局
  • 活佛开示小册下载
  • 在eclipse里配置Android ndk环境 适用于windows mac 和linux[转]
  • 把SOA看清楚
  • yafeilinux.com的开源项目非常好的东西
  • 9月CHINA-PUB-OPENDAY技术沙龙——IPHONE
  • [原]深入对比数据科学工具箱:Python和R 非结构化数据的结构化
  • EventListener原理
  • HTTP那些事
  • Promise面试题,控制异步流程
  • python docx文档转html页面
  • vue-router 实现分析
  • 反思总结然后整装待发
  • 工程优化暨babel升级小记
  • 巧用 TypeScript (一)
  • 实现菜单下拉伸展折叠效果demo
  • 微信端页面使用-webkit-box和绝对定位时,元素上移的问题
  • 优秀架构师必须掌握的架构思维
  • “十年磨一剑”--有赞的HBase平台实践和应用之路 ...
  • ​【已解决】npm install​卡主不动的情况
  • ​力扣解法汇总1802. 有界数组中指定下标处的最大值
  • #每天一道面试题# 什么是MySQL的回表查询
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • (1)SpringCloud 整合Python
  • (31)对象的克隆
  • (6)STL算法之转换
  • (6)设计一个TimeMap
  • (二十三)Flask之高频面试点
  • (一)UDP基本编程步骤
  • (原創) 博客園正式支援VHDL語法著色功能 (SOC) (VHDL)
  • (转)负载均衡,回话保持,cookie
  • . Flume面试题
  • .bat批处理(三):变量声明、设置、拼接、截取
  • .NET delegate 委托 、 Event 事件
  • .NET LINQ 通常分 Syntax Query 和Syntax Method
  • .net 开发怎么实现前后端分离_前后端分离:分离式开发和一体式发布
  • .net利用SQLBulkCopy进行数据库之间的大批量数据传递
  • .NET企业级应用架构设计系列之开场白
  • .secret勒索病毒数据恢复|金蝶、用友、管家婆、OA、速达、ERP等软件数据库恢复
  • /dev/VolGroup00/LogVol00:unexpected inconsistency;run fsck manually
  • :=
  • [ 渗透测试面试篇 ] 渗透测试面试题大集合(详解)(十)RCE (远程代码/命令执行漏洞)相关面试题
  • [8-27]正则表达式、扩展表达式以及相关实战
  • [autojs]逍遥模拟器和vscode对接
  • [BIZ] - 1.金融交易系统特点