温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

nodejs如何实现http2推送信息

发布时间:2021-06-26 10:48:31 来源:亿速云 阅读:977 作者:小新 栏目:大数据

这篇文章给大家分享的是有关nodejs如何实现http2推送信息的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

在http1.x时代,服务器是不能向客户端推送消息的,而在http2里面这成为了一个标准。

HTTP/2被设计为解决HTTP/1.x的许多缺陷。服务器不能向客户端推送消息就是一个缺陷,我们用一个案例来解释一下。

如果一张网页中依赖了很多资源,如js、css、图片等。在HTTP/1.x中浏览器获取HTML后,开始快速扫描整张网页,然后去下载js和css等一些关键资源。而这个过程中有一个瓶颈,那就是浏览器如果要扫描html的话必须先加载html,只有加载完html才能扫描出关键资源,而在加载html的过程中,css和js的加载只有等到html加载完成后才能下载,这里产生一个空闲时刻。HTTP1.x的请求流程如图:

nodejs如何实现http2推送信息

观察图片发现,css和js必须等到html加载完成后,浏览器才能去请求css和js资源。

为了改善延迟,HTTP/2引入了server push,它允许服务端推送资源给浏览器,在浏览器明确地请求之前。一个服务器是清楚的知道一个页面需要哪些附加资源的(当然这些需要开发者的配置),在它响应浏览器第一个请求的时候,可以同步开始推送这些资源。

HTTP2请求流程如图:

nodejs如何实现http2推送信息

对比两张图我们发现,在http2协议下,如果浏览器请求一张网页,服务器在返回html资源的时候,还会将css和js资源一同返回。

这就是http2的推送过程,这里是如何实现的呢?这里需要注意,在上篇文章中,我们了解到http2是全双工通信,并且是基于stream的方式传输信息的,当浏览器请求某个网页时,在建立了tcp链接通道后,这个通道是全双工通信的实现(全双工的意思就是通道可以同时处理客户端的请求和服务端的响应),服务端在响应html内容时,同时将css和js以stream的形式push到客户端。

具体实现流程图如下:

nodejs如何实现http2推送信息

从上文中,我们了解到虽然html信息和css,js一起返回给客户端,但是这里需要注意,虽然是一起返回,但是用的是不同的stream,返回html部分有专门的的stream,返回css和js也有相应的stream,可以理解为从单位到家只有一条路,但是可以乘坐不同的公交车。

从上图中我们可以看到一点有意思的规定,推送数据的流的id是偶数,而请求流并针对请求流响应的流的id是奇数,我猜测这可能是为了方便区分推送流和非推送流的区别。

接着我们利用nodejs的http2模块来实现一下http2的推送功能,代码如下:

const http2 = require('http2');const fs = require('fs');const PORT = 8443;//证书与私钥const  key =fs.readFileSync('./server.key');const  cert= fs.readFileSync('./server.crt');//1、创建服务器const server = http2.createSecureServer({    key,    cert},onRequest);//2、启动服务器server.listen(PORT, (err) => {    if (err) {        console.error(err)        return    }    console.log(`Server listening on ${PORT}`)})//3、设置request事件函数function onRequest(req,res){    const reqPath = req.url === '/' ? '/index.html' : req.url    //打印请求流的id和响应流的id    console.log("req.stream.id:",req.stream.id);    console.log("res.stream.id:",res.stream.id);    //判断是否是首页    if (reqPath === '/index.html') {        //推送1.js        res.stream.pushStream({ ':path': '/1.js' }, (err, pushStream, headers) => {            if (err) throw err;            pushStream.respond({ ':status': 200 });            console.log("pushStream:",pushStream.id)            pushStream.end("console.log(1)");        });        //推送2.js        res.stream.pushStream({ ':path': '/2.js' }, (err, pushStream, headers) => {            if (err) throw err;            console.log("pushStream:",pushStream.id)            pushStream.respond({ ':status': 200 });            pushStream.end("console.log(2)");        });        const fd = fs.openSync('./index.html', 'r');        const stat = fs.fstatSync(fd);        const headers = {            'content-length': stat.size,            'last-modified': stat.mtime.toUTCString(),            'content-type': 'text/html'        };        res.stream.respondWithFD(fd, headers);    }else{        res.end("404")    }}

然后我们再来看一下index.html的代码:

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body><h2>hello world</h2><script src="/1.js"></script><script src="/2.js"></script></body></html>

index.html的代码:很简单,一张网页引入了1.js和2.js。

服务端代码:使用http2模块创建服务器和https、http模块差不多,只不过浏览器在支持http2的时候要求必须设置证书,所以我们需要配置证书和秘钥。

在request事件函数中,我们判断请求的url是否是首页,如果是首页的话,我们通过res.stream.pushStream这个方法配置推送信息,本质上是配置一个tream,这个stream是Http2Stream 类的实例,res.stream.pushStream需要两个参数,第一个参数是一个对象,在这个对象中配置这个流的path,客户端可以通过这个path使用这个流。

第二个参数为一个回调函数,回调函数第一个参数是err,第二个参数是一个stream,这个stream也是Http2Stream 类的实例。

这个stream是如何设置的呢?我们通过stream对象上的两个方法来设置,respond方法设置stream的头部信息,end方法设置stream的body信息,他们分别对应流中的header帧和body帧。

设置完这两个需要被推送的流之后,再来设置主流html的响应流,这里我们使用strem实例的另外一个方法respondWidthFD来设置响应流。这个方法需要设置两个参数,第一个参数为文件描述符,第二个参数为header信息。文件描述符中存储着流的主体信息,header中保存了流的响应头信息。

从stream两组设置方法,我们可以看出流至少包含两部分信息,header帧和body帧。

代码中我们分别打印了流的id值,我们运行代码看一下打印结果,结果如图:

nodejs如何实现http2推送信息

我们可以看到这和我们前面说的一样,推送流的id是偶数设置,非推送流的id为奇数。

然后我们看一下浏览器中network的截图:

nodejs如何实现http2推送信息

我们看到所有资源都是用http2协议进行请求响应的,而1.js和2.js是服务器在响应html的时候同时push过来的,时间只有1ms。

总结一下:本篇文章主要讲了http2的推送原理,以及如何使用nodejs的http2模块搭建一台http2服务器来实现推送功能。

这里需要注意的几点如下:

1、http2的推送是基于流和全双工通信

2、推送流的id是偶数,非推送流的id为奇数。

3、服务端推送的内容是基于客户端的需要,这里需要前后端工程师通力合作。

4、在推送数据时尽量推送关键性资源,如css、js,关键的背景图等等,而非关键性资源尽量不要推送。

5、nodejs中stream实例配置的两种方式,respond和end或者respondWidthFD,不论哪种方式都需要设置头信息和body信息。

nodejs如何实现http2推送信息

感谢各位的阅读!关于“nodejs如何实现http2推送信息”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI