Node.js開發(fā)指南:利用Socket.IO與doT提升性能表現(xiàn)
譯文教程介紹
- 難度: 中級(jí)
- 預(yù)計(jì)完成時(shí)間: 20分鐘
如果您的網(wǎng)站對于向客戶機(jī)發(fā)送數(shù)據(jù)較為依賴,那么使用客戶端模板以及WebSocket能夠顯著提高其性能表現(xiàn)。在今天的教程中,我們就一起來了解如何實(shí)現(xiàn)這一目標(biāo)。
簡介
我 們將以現(xiàn)有應(yīng)用程序?yàn)槠瘘c(diǎn),一步步了解如何使其在高流量環(huán)境下?lián)碛懈斓捻憫?yīng)速度與更可靠的運(yùn)行表現(xiàn)。我將向大家展示如何從應(yīng)用程序代碼中準(zhǔn)確定位對應(yīng)代 碼段,如何對其進(jìn)行修改以提升運(yùn)行性能。不過首先大家需要下載我準(zhǔn)備好的范例應(yīng)用。這款應(yīng)用的內(nèi)容非常簡單,運(yùn)行目的在于隨機(jī)顯示服務(wù)器當(dāng)中的帖子內(nèi)容 ——不過對于我們這篇指南文章來講,這已經(jīng)足夠了。
***步: 準(zhǔn)備
對我們已經(jīng)下載完成的文件進(jìn)行解壓,為其選定文件夾或者保存位置,而后加以運(yùn)行:
現(xiàn)在我們前往http://localhost:8080/并查看其內(nèi)容。這時(shí)大家應(yīng)該只能看到一個(gè)按鈕。各位還需要準(zhǔn)備一款安裝了各類開發(fā)者工具的瀏覽器,這樣就能掌握HTTP請求的實(shí)際大小。打開開發(fā)者工具,而后訪問Network標(biāo)簽。接下來點(diǎn)擊幾下該按鈕,注意/getpost請求的大?。?/span>
這條請求只有830字節(jié),對吧?好的,想象一下,當(dāng)我們的網(wǎng)站人氣爆棚時(shí),可能同時(shí)有一百多萬用戶想看到這篇帖子,這時(shí)請求的數(shù)據(jù)總量將達(dá)到約830MB。請注意,是每篇帖子830MB!這可就不是個(gè)小數(shù)目了。
第二步: 檢查
在 第二步中,我將帶領(lǐng)大家了解如何在應(yīng)用中找到能夠提升性能表現(xiàn)的對應(yīng)代碼片段。在前一步中,大家已經(jīng)找到了用于獲取帖子內(nèi)容的請求,現(xiàn)在我們需要了解代碼 是如何實(shí)現(xiàn)這一過程的。大家可以利用自己熟悉的代碼編輯器打開index.js文件,其中第16到第20行內(nèi)容如下所示:
- varpostTemplate = dot(fs.readFileSync('./post.dot'));
- app.get('/getpost', function(req, res) {
- res.end(postTemplate(posts[Math.floor(Math.random() * 3)]));
- });
就是它了!首先,帖子的模板會(huì)被編譯至postTemplate變量當(dāng)中。接下來,該模板會(huì)在/getpostGET請求中實(shí)現(xiàn)提交。這是一種非常典型的解決辦法,可以說是乏善可陳。我們要對其進(jìn)行變更以改進(jìn)性能表現(xiàn)。
第三步: 設(shè)置Socket.IO
To begin the improvements, first, install Socket.IO. In your terminal type:為了實(shí)現(xiàn)性能提升,我們首先需要安裝Socket.IO。大家需要在命令行終端內(nèi)輸入:
- npm installsocket.io
等待命令執(zhí)行完成。通過將以下代碼行添加到index.js的全部require之后將socket.io引入代碼:
- varsio = require('socket.io');
現(xiàn)在大家必須對Express的設(shè)置進(jìn)行修改,以使其與Socket.IO順利協(xié)作。首先,在app definition之后加入下列內(nèi)容:
- varserver = require('http').createServer(app);
- vario = require('socket.io').listen(server);
- server.listen(8080);
接下來移除該文件中的***一行:
之所以這么做,是因?yàn)镾ocket.IO的運(yùn)作與HTTP Server緊密相關(guān)——而非Express app。
現(xiàn)在,如果大家運(yùn)行該應(yīng)用,應(yīng)該會(huì)在自己的終端中看到如下所示的內(nèi)容:
#p#
第四步: 客戶端模板
為了著手提升應(yīng)用性能,大家需要將 經(jīng)過編譯的模板保存在客戶端當(dāng)中。JavaScript文件會(huì)駐留在緩存當(dāng)中,因此我們只要下載一次即可。為了編譯模板,我們需要訪問 http://olado.github.io/doT/index.html并下滾到Usage部分。由于我們不必在用戶每一次訪問網(wǎng)站時(shí)都對模板進(jìn)行 編譯,因此大家完全可以直接把編譯后的函數(shù)添加到代碼當(dāng)中。打開post.dot文件,將其內(nèi)容如下所示粘貼到Template字段當(dāng)中:
現(xiàn)在將該字段的內(nèi)容復(fù)制并粘貼到static/main.js文件的最初始位置。變更或者移除anonymous函數(shù)名稱并將其分配至postTemplate變量,具體方式如下:
- varpostTemplate = function(it) { ... }
然后打開index.js文件并移除所有未使用的代碼行,因?yàn)閺默F(xiàn)在開始,我們已經(jīng)不必在服務(wù)器端對模板進(jìn)行編譯了:
- vardot = require('dot').template;
- varfs = require('fs');
- ...
- varpostTemplate = dot(fs.readFileSync('./post.dot'));
post.dot 文件也可以刪掉,沒關(guān)系的。
第五步: 從AJAX到WebSocket
相 對于以往利用AJAX實(shí)現(xiàn)與服務(wù)器通信的做法,現(xiàn)在我們轉(zhuǎn)而使用WebSocket。***的辦法是使用Socket.IO,這是因?yàn)閃ebSocket API本身并不提供故障轉(zhuǎn)移功能——理由是用戶的瀏覽器不支持。服務(wù)器已經(jīng)設(shè)置完成,因此我們現(xiàn)在需要與之進(jìn)行對接。首先,將下列代碼添加到 static/index.html文件(在main.js之前)的head位置:
- <scriptsrcscriptsrc="/socket.io/socket.io.js"></script>
接下來,打開static/main.js文件并在模板definition之后添加以下代碼:
- varsocket = io.connect();
它 將與Socket.IO服務(wù)器相連(請注意,大家必須提前將Socket.IO的腳本添加到頁面當(dāng)中)。由于在我們的實(shí)驗(yàn)環(huán)境中,服務(wù)器與客戶端運(yùn)行在同 一臺(tái)主機(jī)當(dāng)中,因此大家不必再為該函數(shù)添加任何額外參數(shù)?,F(xiàn)在我們要做的是為該socket添加一個(gè)事件監(jiān)聽器,這樣帖子內(nèi)容獲取完畢后我們就能及時(shí)得到 提示。將下列代碼添加到之前代碼行的后面:
- socket.on('getpost', function(data) {
- $('button').after(postTemplate(data));
- });
如大家所見,回調(diào)命令的內(nèi)容與jQuery的$.ajax()方法中的success回調(diào)并無區(qū)別,但它會(huì)首先運(yùn)行數(shù)據(jù)中的模板函數(shù)?,F(xiàn)在,將$.ajax()調(diào)用替代為以下內(nèi)容:
- socket.emit('getpost');
這一行代碼的作用在于通知服務(wù)器,用戶希望顯示一篇新帖子。當(dāng)然,在現(xiàn)實(shí)生活的應(yīng)用程序內(nèi),服務(wù)器會(huì)在帖子發(fā)布后立刻加以發(fā)送。
第六步: 發(fā)送帖子
到這里,客戶端已經(jīng)能夠與服務(wù)器對接并請求獲取帖子內(nèi)容,但服務(wù)器還無法正確響應(yīng)隨機(jī)帖子。現(xiàn)在我們打開index.js文件并對內(nèi)容加以變更。由原本的:
- app.get('/getpost', function(req, res) {
- res.end(postTemplate(posts[Math.floor(Math.random() * 3)]));
- });
變更為:
- io.sockets.on('connection', function(socket) {
- socket.on('getpost', function() {
- socket.emit('getpost', posts[Math.floor(Math.random() * 3)]);
- });
- });
這 將使服務(wù)器將getpost句柄與所有客戶端相連,并利用隨機(jī)帖子內(nèi)容作為響應(yīng)?,F(xiàn)在大家可以再次運(yùn)行應(yīng)用程序以查看實(shí)際效果。接下來我們要再次打開瀏覽 器中的開發(fā)者工具、找到Network標(biāo)簽并加以過濾,這樣大家就只會(huì)看到WebSocket。現(xiàn)在點(diǎn)擊這個(gè)惟一可見的對象,大家應(yīng)該看到瀏覽器與服務(wù)器 之間的傳輸?shù)臄?shù)據(jù)——是的,請求大小與文章開頭的初始狀態(tài)相比有了明顯縮減。這是因?yàn)閯傞_始請求當(dāng)中還包含有服務(wù)器端模板與AJAX內(nèi)容(長度單位為‘字 節(jié)’):
總結(jié)
如各位所見,利用WebSocket以及客戶端模板(幾乎一定)能夠改進(jìn)應(yīng)用程序的性能表現(xiàn)及耐用性。我敢肯定,很多網(wǎng)站都采用這種方式提升自己的響應(yīng)效果。當(dāng)然,我也希望各位朋友能夠利用這項(xiàng)技巧為自己的移動(dòng)及桌面系統(tǒng)用戶帶來更出色的使用體驗(yàn)。
原文鏈接:http://net.tutsplus.com/tutorials/javascript-ajax/node-js-better-performance-with-socket-io-and-dot/