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