這篇文章給大家分享的是有關(guān)nodejs如何實(shí)現(xiàn)http2推送信息的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過來看看吧。
10年積累的成都網(wǎng)站設(shè)計(jì)、網(wǎng)站制作、外貿(mào)營銷網(wǎng)站建設(shè)經(jīng)驗(yàn),可以快速應(yīng)對(duì)客戶對(duì)網(wǎng)站的新想法和需求。提供各種問題對(duì)應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識(shí)你,你也不認(rèn)識(shí)我。但先網(wǎng)站設(shè)計(jì)后付款的網(wǎng)站建設(shè)流程,更有沙河免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。
在http1.x時(shí)代,服務(wù)器是不能向客戶端推送消息的,而在http2里面這成為了一個(gè)標(biāo)準(zhǔn)。
HTTP/2被設(shè)計(jì)為解決HTTP/1.x的許多缺陷。服務(wù)器不能向客戶端推送消息就是一個(gè)缺陷,我們用一個(gè)案例來解釋一下。
如果一張網(wǎng)頁中依賴了很多資源,如js、css、圖片等。在HTTP/1.x中瀏覽器獲取HTML后,開始快速掃描整張網(wǎng)頁,然后去下載js和css等一些關(guān)鍵資源。而這個(gè)過程中有一個(gè)瓶頸,那就是瀏覽器如果要掃描html的話必須先加載html,只有加載完html才能掃描出關(guān)鍵資源,而在加載html的過程中,css和js的加載只有等到html加載完成后才能下載,這里產(chǎn)生一個(gè)空閑時(shí)刻。HTTP1.x的請(qǐng)求流程如圖:
觀察圖片發(fā)現(xiàn),css和js必須等到html加載完成后,瀏覽器才能去請(qǐng)求css和js資源。
為了改善延遲,HTTP/2引入了server push,它允許服務(wù)端推送資源給瀏覽器,在瀏覽器明確地請(qǐng)求之前。一個(gè)服務(wù)器是清楚的知道一個(gè)頁面需要哪些附加資源的(當(dāng)然這些需要開發(fā)者的配置),在它響應(yīng)瀏覽器第一個(gè)請(qǐng)求的時(shí)候,可以同步開始推送這些資源。
HTTP2請(qǐng)求流程如圖:
對(duì)比兩張圖我們發(fā)現(xiàn),在http2協(xié)議下,如果瀏覽器請(qǐng)求一張網(wǎng)頁,服務(wù)器在返回html資源的時(shí)候,還會(huì)將css和js資源一同返回。
這就是http2的推送過程,這里是如何實(shí)現(xiàn)的呢?這里需要注意,在上篇文章中,我們了解到http2是全雙工通信,并且是基于stream的方式傳輸信息的,當(dāng)瀏覽器請(qǐng)求某個(gè)網(wǎng)頁時(shí),在建立了tcp鏈接通道后,這個(gè)通道是全雙工通信的實(shí)現(xiàn)(全雙工的意思就是通道可以同時(shí)處理客戶端的請(qǐng)求和服務(wù)端的響應(yīng)),服務(wù)端在響應(yīng)html內(nèi)容時(shí),同時(shí)將css和js以stream的形式push到客戶端。
具體實(shí)現(xiàn)流程圖如下:
從上文中,我們了解到雖然html信息和css,js一起返回給客戶端,但是這里需要注意,雖然是一起返回,但是用的是不同的stream,返回html部分有專門的的stream,返回css和js也有相應(yīng)的stream,可以理解為從單位到家只有一條路,但是可以乘坐不同的公交車。
從上圖中我們可以看到一點(diǎn)有意思的規(guī)定,推送數(shù)據(jù)的流的id是偶數(shù),而請(qǐng)求流并針對(duì)請(qǐng)求流響應(yīng)的流的id是奇數(shù),我猜測(cè)這可能是為了方便區(qū)分推送流和非推送流的區(qū)別。
接著我們利用nodejs的http2模塊來實(shí)現(xiàn)一下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、創(chuàng)建服務(wù)器
const server = http2.createSecureServer({
key,
cert
},onRequest);
//2、啟動(dòng)服務(wù)器
server.listen(PORT, (err) => {
if (err) {
console.error(err)
return
}
console.log(`Server listening on ${PORT}`)
})
//3、設(shè)置request事件函數(shù)
function onRequest(req,res){
const reqPath = req.url === '/' ? '/index.html' : req.url
//打印請(qǐng)求流的id和響應(yīng)流的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")
}
}
然后我們?cè)賮砜匆幌耰ndex.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的代碼:很簡單,一張網(wǎng)頁引入了1.js和2.js。
服務(wù)端代碼:使用http2模塊創(chuàng)建服務(wù)器和https、http模塊差不多,只不過瀏覽器在支持http2的時(shí)候要求必須設(shè)置證書,所以我們需要配置證書和秘鑰。
在request事件函數(shù)中,我們判斷請(qǐng)求的url是否是首頁,如果是首頁的話,我們通過res.stream.pushStream這個(gè)方法配置推送信息,本質(zhì)上是配置一個(gè)tream,這個(gè)stream是Http2Stream 類的實(shí)例,res.stream.pushStream需要兩個(gè)參數(shù),第一個(gè)參數(shù)是一個(gè)對(duì)象,在這個(gè)對(duì)象中配置這個(gè)流的path,客戶端可以通過這個(gè)path使用這個(gè)流。
第二個(gè)參數(shù)為一個(gè)回調(diào)函數(shù),回調(diào)函數(shù)第一個(gè)參數(shù)是err,第二個(gè)參數(shù)是一個(gè)stream,這個(gè)stream也是Http2Stream 類的實(shí)例。
這個(gè)stream是如何設(shè)置的呢?我們通過stream對(duì)象上的兩個(gè)方法來設(shè)置,respond方法設(shè)置stream的頭部信息,end方法設(shè)置stream的body信息,他們分別對(duì)應(yīng)流中的header幀和body幀。
設(shè)置完這兩個(gè)需要被推送的流之后,再來設(shè)置主流html的響應(yīng)流,這里我們使用strem實(shí)例的另外一個(gè)方法respondWidthFD來設(shè)置響應(yīng)流。這個(gè)方法需要設(shè)置兩個(gè)參數(shù),第一個(gè)參數(shù)為文件描述符,第二個(gè)參數(shù)為header信息。文件描述符中存儲(chǔ)著流的主體信息,header中保存了流的響應(yīng)頭信息。
從stream兩組設(shè)置方法,我們可以看出流至少包含兩部分信息,header幀和body幀。
代碼中我們分別打印了流的id值,我們運(yùn)行代碼看一下打印結(jié)果,結(jié)果如圖:
我們可以看到這和我們前面說的一樣,推送流的id是偶數(shù)設(shè)置,非推送流的id為奇數(shù)。
然后我們看一下瀏覽器中network的截圖:
我們看到所有資源都是用http2協(xié)議進(jìn)行請(qǐng)求響應(yīng)的,而1.js和2.js是服務(wù)器在響應(yīng)html的時(shí)候同時(shí)push過來的,時(shí)間只有1ms。
總結(jié)一下:本篇文章主要講了http2的推送原理,以及如何使用nodejs的http2模塊搭建一臺(tái)http2服務(wù)器來實(shí)現(xiàn)推送功能。
這里需要注意的幾點(diǎn)如下:
1、http2的推送是基于流和全雙工通信
2、推送流的id是偶數(shù),非推送流的id為奇數(shù)。
3、服務(wù)端推送的內(nèi)容是基于客戶端的需要,這里需要前后端工程師通力合作。
4、在推送數(shù)據(jù)時(shí)盡量推送關(guān)鍵性資源,如css、js,關(guān)鍵的背景圖等等,而非關(guān)鍵性資源盡量不要推送。
5、nodejs中stream實(shí)例配置的兩種方式,respond和end或者respondWidthFD,不論哪種方式都需要設(shè)置頭信息和body信息。
感謝各位的閱讀!關(guān)于“nodejs如何實(shí)現(xiàn)http2推送信息”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!
分享題目:nodejs如何實(shí)現(xiàn)http2推送信息
網(wǎng)頁路徑:http://www.rwnh.cn/article12/jcjpgc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供面包屑導(dǎo)航、移動(dòng)網(wǎng)站建設(shè)、品牌網(wǎng)站設(shè)計(jì)、python、網(wǎng)站制作、靜態(tài)網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)