大家都在用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…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值