all about nodejs
TRANSCRIPT
瞭解NodeJS開發技術
by Fillano
課程主要內容
• NodeJS 的背景知識• 如何撰寫 NodeJS 程式• 幾個 code example 展示與說明• 在 Windows 環境中執行 NodeJS• 如何找到更多資源
作者、 Javascript、 V8及其它NodeJS的背景知識
什麼是NodeJS
• 它主要是一個伺服器端的 Javascript 環境• 它提供了符合 CommonJS1.0 規格的模組機制,擴充功能
非方便• 只要能使用模組來擴充功能,實際使用上並不限於伺服器
程式
什麼是NodeJS
• 舊瓶裝新酒• 1996 – Netscape Livewire in Netscape Enterprise Server• ASP with Jscript, Jscript.NET• Mozilla Rhino
• Flowscript for Apache Cocoon 2.1• Javascript Webflow for Spring• Helma (http://helma.org)
• RingoJS (http://ringojs.org/)
什麼是NodeJS
• 舊瓶裝新酒• Mozilla SpiderMonkey
• Aptana Jaxer (http://jaxer.org/)• couchDB (RESTful API)
• Google V8• v8cgi (http://code.google.com/p/v8cgi/)• v8juice (http://code.google.com/p/v8-juice/)
• wikipedia: Comparison of server-side JavaScript solutions
什麼是NodeJS
• 全新的生命力 不需要倚賴其他伺服器 類似 v8juice 與 jslib (http://jslib.mozdev.org/) 接下來會談到的成功因素
為什麼這麼熱門
• 因為執行速度非常快• 有多快?一些比較:
http://shootout.alioth.debian.org/ vs php (
benchmarking nodejs basic performance tests against apache-php)
vs ruby (express vs sinatra benchmarks) vs ringojs (RingoJS vs. Node.js: Runtime Values)
為什麼它這麼快?
• 它使用了 Google V8 Javascript 引擎 特別的 JIT 技術:兩階段 JIT
AST :將 Javascript 剖析成抽象語法樹 Generic CodeGen :直接產生尚未最佳化的機器碼執行
目前使用的最佳化技術 Cranshaft 執行時期追蹤與 Profiling
將型別資訊紀錄在相關 AST 節點中 Optimized CodeGen
四階段最佳化,產生可利用暫存器存放變數的機器碼
為什麼它這麼快?
• Evented I/O I/O 的速度,遠比 CPU 執行的速度慢,所以最有效率的方法
是在 I/O 完成時,由系統通知程式執行完畢,可以處理 I/O 動作執行的結果
為什麼它這麼快?
• Evented I/O 舊方法: select, poll ,需要用兩個很慢的方法來監視資源
輪詢:每隔一段時間詢問系統是否有結果 遍歷:走訪每一個要監聽的檔案與網路 port
為什麼它這麼快?
• Evented I/O 新方法: evented I/O ,告訴系統要監控的資源,當有變動時,
系統以事件通知 Linux: epoll BSD: kqueue Windows, Solaris: IOCP (I/O Completion Port)
誰創造了 NodeJS Ryan Dahl
• 在德國工作的美籍 Freelancer ,專長: Interruptable Parser Event loops(event-machine, gearman…) Response time historgram
誰創造了 NodeJS Ryan Dahl
• 一些開放原始碼專案的發起者: Ebb web server EY Load Balancer module for Nginx
誰創造了 NodeJS Ryan Dahl
• 為了解決網站伺服器效能的問題,嘗試了: Ruby: Event Machine Python: Twisted
• 但是都不能滿意,在 Google V8 Engine 發表後,決定自己寫一個: 2009 JSConf 發表,獲得全場起立鼓掌 Crockford 曾說:這是 Javascript 發展過程的一個重要案例,
會影響未來 ECMA-262 規格的制定
誰創造了 NodeJS Issac Schlueter 及其它開發者
• Issac Schlueter: NodeJS 上最多人使用的套件管理系統 -NPM 的作者,目前是 Ryan Dahl 在 Joyent 的同事
• 更多貢獻者:• Bert Belder(Release manager), Tim Caswell(How to node
website), Felix Geisendorfer, TJ Hollowaychuck(Express Framework), Paul Querna, Matt Ranney, Mikeal Rogers, Micheil Smith etc…
哪裡可以找到 NodeJS
• http://nodejs.org 最新版本的原始碼檔案下載 最新版本的 Windows 可執行檔下載 最新版本的 API文件
• http://github.com/joynet/node 原始碼 Repository wiki :重點 - 如何在不同作業系統中編譯 NodeJS Issue Tracker
誰在使用 NodeJS
• Plurk(www.plurk.com) http://www.slideshare.net/amix3k/comet-with-nodejs-and-v8
• Linkedin(www.linkedin.com) How LinkedIn used Node.js and HTML5 to build a better, faster ap
p
• 其它,參考: Projects, Applications, and Companies Using Node (列表中有一些是提供 NodeJS Hosting 服務的公司,他們
自己也利用 NodeJS 開發相關管理方案,例如 nodejitsu)
使用 NodeJS 的時機 快速反應!
• 可以但並不適用於所有案例• 重點:當快速反應是最重要考量時• 並不適合需要大量運算的案例
使用 NodeJS 的時機 快速反應!
• 單一執行緒與 event loop Javascript 程式本身只能在一個執行緒中執行 所有事件都是在一個 event loop依序執行 所以反應速度還是會隨著連線數上昇而逐漸下降
• 解決方法 在單一或多個機器上同時執行多個 node instance ,使用
proxy做 load balance 新版的 V8 引擎可以支援一個行程多個 instance
當前開發狀態
• v0.5x( 開發版 )支援Microsoft Windows
支援 child_process支援 IOCP 可動態載入的原生模組 其它
支援 Visual C++之前只能在 Cygwin 及 MSYS 環境中編譯 v0.5.6 將可以在 Visual C++ Express正確編譯
當前開發狀態
• 關鍵: libuv支援不同 OS 的 evented I/O 抽象層支援Microsoft Windows 的 I/O Completion Port 機制讓 NodeJS 抽換掉對於 libeio, libevent, libev等的直接依賴 在 Windows 環境中可使用 Visual C++編譯
Javascript知識、效能、 NodeJS開發環境如何撰寫 NodeJS程式
最簡單的程式範例 hello world 伺服器• 一頁就放的下的程式
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World.');
}).listen(1337, "127.0.0.1");
console.log('Server running at http://127.0.0.1:1337/');
最簡單的程式範例 hello world加上 Express Framework
• 一頁就放的下的程式
var express = reuqire('express'), app = express.createServer();app.get('/', function(req, res){ res.send('Hello World.');});app.listen(3000);
Javascript 背景知識 伺服器端的 Javascript
• 與瀏覽器中有什麼不同?沒有 DOM物件 Global 提供的環境不一樣
• 其它地方大同小異 因為都是 Javascript (ECMAScript) 以 NodeJS 來說,大量使用非同步的執行方式,但是與在瀏覽器中事件與非同步的寫法也差不多
Javascript 背景知識 event loop
Javascript 背景知識 event loop
• Javascript 程式的 Life Cycle第一步先執行 Global Context 中的程式碼 接下來,用 event loop 的方式執行所有事件函數,直到結束 如果在瀏覽器中,可以利用動態新增 script tag 的方式,再次
執行載入的 script 中 Global Context 中的程式碼,不過在NodeJS 不會有這個狀況發生
所以,大部份時間可能都是在執行函數
Javascript 背景知識 event loop
• 優點沒有執行緒的額外負擔,反應速度快共用的變數不需鎖定,程式結構簡單
• 缺點某一函數執行時間長,就會推遲其它函數執行無法把負載分散到不同的 CPU
• 解決方法(以 NodeJS 為例) 同時執行多個 instance ,利用 proxy做負載均衡 Intel 的計畫,讓 Javascript 可以在多核心環境中進行平行處
理 https://github.com/RiverTrail/RiverTrail 目前只支援 Firefox
Javascript 背景知識 事件與 callback函數• 通常在使用事件時,會傳遞給它一個函數,利用這個函數來執
行事件觸發時要職行的動作,這個函數就叫做 callback函數
var elem = document.getElementById(‘target’);elem.addEventListener(‘click’, function(e) {
//this is a callback function}, false);
Javascript 背景知識 事件與 callback函數• 在瀏覽器中,通常很少超過兩層
var elem = document.getElementById(‘target’);elem.addEventListener(‘click’, function(e) {
req.onreadystatechange = function() {if(this.readyState===4&&this.status===200) {
var that = this;window.setTimeout(function(){
alert(that.responseTest)}, 500)
}}
}, false);
Javascript 背景知識 事件與 callback函數• 在 NodeJS 環境中,有非常多的操作是用 callback 來完成,例如
這一段 mongo db 的範例
var p_client = new Db('integration_tests_20', new Server("127.0.0.1", 27017, {}), {'pk':CustomPKFactory});p_client.open(function(err, p_client) { p_client.dropDatabase(function(err, done) { p_client.createCollection('test_custom_key', function(err, collection) { collection.insert({'a':1}, function(err, docs) { collection.find({'_id':new ObjectID("aaaaaaaaaaaa")}, function(err, cursor) { cursor.toArray(function(err, items) { test.assertEquals(1, items.length); p_client.close(); });});});});});});
Javascript 背景知識 事件與 callback函數
• 為什麼會出現這麼多層的 callbacks ? 重要的操作幾乎都透過 callback已非同步的方式完成 所以常常在 callbacks 中使用其他功能,就需要另外加一層
callbacks 在許多功能需要循序執行時,就需要在 callbacks 中使用下一
個步驟的功能,這些還是需要 callbacks 來完成
Javascript 背景知識 事件與 callback函數
• 複雜 callbacks 的問題 程式邏輯會分散到各個 callbacks ,比較難除錯 不容易做單元測試
• 解決方式借助一些模組的幫助,將這些非同步的 callbacks改成同步的形式(底層還是使用非同步)
不要用匿名函數做 callbacks ,這樣對它做單元測試就比較容易
Javascript 背景知識 撰寫 Javascript 程式的一些原則
• 不要污染 Global Scope 利用 Object把函數及變數 Group 起來 (namespacing) 利用立即執行的匿名函數,把在 Global Scope 執行的程式包
裝起來 不過只要好好使用模組,在 NodeJS 這不是大問題
• 簡單的性能策略注意變數 Scope 解析的問題 需要花時間處理的程式,可以切割成數個函數,利用
process.nextTick() 非同步執行
V8 Javascript VM 的性能 一些簡單的原則
• V8 會依照函數執行的次數作為參考,進行最佳化( hot functions)某個函數預期它會在 NodeJS instance 生命週期中執行越多次,調整它對於效能就會更有效果
某些操作在 Javascript 中並沒有非同步執行的版本,例如JSON.parse/stringify ,而這些操作比較花時間。這時可以找一找是否有人實作非同步的版本(模組)
例如: https://github.com/dominictarr/JSONStream
V8 Javascript VM 的性能 一些簡單的原則
• 但是有一些地方會妨礙 V8做最佳化無法決定 scope 中變數的型別時某些 Javascript函數,無法最佳化,所以使用到的話… 例如:用 Array.prototype.slice.call(arguments,1) 來把
arguments轉換成陣列就比 for(var i=0; i<arguments.length; i++) 慢,因為後者可以最佳化
開發 NodeJS 程式 環境建置
• 取得 NodeJS 可執行檔 Unix-Like 環境
需要預先安裝 Python 及 GCC4.0 以上 在 nodejs.org 網站取得原始碼 解開後依序執行 ./configure、make 需要安裝到系統中時,執行 make install
開發 NodeJS 程式 環境建制
• 取得 NodeJS 可執行檔 Windows 環境
安裝 Cygwin或是 mingw+msys 環境,還是需要 Python 及GCC4.0 以上
解開後依序執行 ./configure、make 需要安裝到系統中時,執行 make install 如果需要在純 windows 環境中執行 node.exe ,還需要把
Cygwin或是 msys 提供的一些 dll 檔複製到同一個目錄 如果不知道要複製哪些,執行 node.exe 會出現找不到這些 dll 檔
的錯誤訊息,可以當作參考
開發 NodeJS 程式 環境建制
• 取得 NodeJS 可執行檔 Windows 環境
V0.5.6之後,可以直接使用 Microsoft Visual C++ 2010 來編譯,不過這個開發版本尚未釋出
不想自己編譯的話, V0.5.x 都有提供已編譯好的執行檔
開發 NodeJS 程式 環境建制
• 安裝 NPM(node package manager) Unix-like 環境
需要預先安裝 curl參考 npmjs.org首頁上提供的方式,執行 one line install
Windows 環境 目前在 Windows 環境中還無法執行 npm 但是可利用 NODE_PATH 環境變數指定模組的預設路徑 到 search.npmjs.org 網站上尋找要安裝的模組參考依賴性,把相關的模組一起安裝到 NODE_PATH
開發 NodeJS 程式 Global Scope 環境• Javascript 的運行環境是由 host透過存在於 Global Scope 的物
件或函數來提供的例如在 node.exe 的 console 中執行以下程式,就可以列舉出 Global Scope 中的物件與函數
> (function(o){for(var i in o) console.log(i)})(this);
開發 NodeJS 程式 Global Scope 環境• 結果可以看到:> (function(o){for(var i in o) console.log(i)})(this);ArrayBufferInt8ArrayUint8ArrayInt16ArrayUint16ArrayInt32ArrayUint32ArrayFloat32ArrayFloat64ArrayDataViewglobal……
TypedArray 相關物件
Global物件的別名,就像瀏覽器環境中的 window物件
開發 NodeJS 程式 Global Scope 環境• 結果可以看到:
…processGLOBALrootBuffersetTimeoutsetIntervalclearTimeoutclearIntervalconsole
處理行程的物件,有行程相關資訊、取得工作目錄等功能
用來處理 binary 資料的物件
用來做 stdio 的物件,可以輸出錯誤、 debug、 log等資訊
跟瀏覽器中的一樣啦
Global物件的別名,就像瀏覽器環境中的 window物件
開發 NodeJS 程式 Global Scope 環境• 還漏掉一些(不會列舉出來):
…__dirname__pathnameexportsmodule
程式所在目錄的絕對路徑所執行 js 檔案的絕對路徑撰寫模組時,用來將介面輸出到呼叫端的物件其實就是 module.exports
提供目前模組的功能介面與資訊
如果撰寫「模組」,這幾個顯示的都是模組「 local」的資訊
開發 NodeJS 程式 核心模組• 核心模組是編譯在 NodeJS 執行檔中的模組• 與外部模組一樣,透過下面方式載入使用
var http = require(‘http’);// 將 http 模組載入,指派給 http 變數
var server = http.createServer(function(request, response) {//分析 request 資訊,寫入 response
});server.listen(80, ‘127.0.0.1’);
開發 NodeJS 程式 核心模組 -console (STDIO)
• NodeJS 提供的核心模組 提供標準輸入輸出功能,會自動載入 重要的功能:
console.log()/console.info(): 輸出訊息到標準輸出 console.warn()/console.error(): 輸出訊息到標準錯誤 console.dir(物件 ): 把物件資訊輸出到標準錯誤 console.trace(): 傾印程式當前位置的 stack trace 資訊 console.assert(): 就是 assert.ok() ,用來做測試
開發 NodeJS 程式 核心模組 -timers
• NodeJS 提供的核心模組 會自動載入 重要的功能(跟瀏覽器中的一樣)
setTimeout(callback, time) clearTimeout(tid) setInterval(callback, time) clearInterval(tid)
開發 NodeJS 程式 核心模組 -process
• NodeJS 提供的核心模組 提供行程資訊與操作,會自動載入 重要的功能
process.stdout / stderr: 寫入標準輸出 /標準錯誤的 writeable stream物件
process.stdin: 讀取標準輸入的 readable stream物件 process.argv: 程式啟動時傳入的參數 process.env: 取得系統環境變數 process.nextTick(callback): 讓 callback 非同步執行 process.cwd() / chdir(): 取得 /修改目前工作目錄 process.exit(code=0): 結束行程,返回訊息代碼
開發 NodeJS 程式 核心模組 -util
• NodeJS 提供的核心模組 提供一些常用的工具函數,使用 require(‘util’)載入 重要的功能
util.format(): 返回格式化字串 util.debug(string): 輸出訊息到標準錯誤,執行時會停止所有程
式 util.log(string): 輸出訊息到標準輸出,並加上時間資訊 util.inspect(object): 回傳物件的代表資訊 util.pump(readableStream, writeableStream): 將讀入直接轉
到寫出 util.inherits(target, parent): 讓目標物件繼承父物件
開發 NodeJS 程式 核心模組 -events.EventEmitter
• NodeJS 提供的核心模組 提供事件機制,使用到事件都要繼承它,使用
require(‘events’).EventEmitter載入 重要的功能
emitter.on(‘event’, listener): 指定事件處理函數給特定事件 emitter.once(): 同上,但是函數只會執行一次 emitter.removeListener(‘evnet’, listener): 移除事件處理函數 emitter.removeAllListeners(‘evnet’): 移除指定事件的所有處理函數
emitter.listeners(‘event’): 返回指定事件的處理函數陣列 emitter.emit(‘event’, [參數 1], [參數 2], …): 執行指定事件的處
理函數
開發 NodeJS 程式 核心模組 -Buffer
• NodeJS 提供的核心模組 用來處理 binary 資料,自動載入 重要的功能
new Buffer(): 建構子 buffer.write(): 將字串寫入 Buffer buffer.copy(): 把 buffer 的資料拷貝給指定的 buffer物件 buffer.length: 取得 buffer 的長度 buffer[index]: 取得 buffer索引位置的資料
開發 NodeJS 程式 核心模組 -streams
• NodeJS 提供的核心模組 用來處理各種資料的 I/O 的抽象結構,通常包裝成不同物件的成員自動載入,有 Readable 及 Writeable 兩種
重要的功能 Readable Stream
‘data’ 事件 : 會在資料到達時觸發 pipe(dest, [opt]): 可以把輸入 (Readable)轉向輸出 (Writeable)
Writeable Stream write(buffer)/write(string, encoding): 將資料寫入 end()/end(string, encoding,)/end(buffer): 結束資料,不再寫入
開發 NodeJS 程式 核心模組 -crypto
• NodeJS 提供的核心模組 提供處理加解密的各個方法,透過 require(‘crypto’)載入 重要的功能
createCredentials()/createHmac()/creatCipher()/createDecipher()/ createSign()/createVerify()/createDiffeHellman()等 : 產生各種用來做加解密、 hash、簽章、驗證等物件
update(data): 用來把資料傳給上述物件,可搭配 stream 的方式在收到資料時傳給它,最後再用各物件的個別的操作來產生結果
開發 NodeJS 程式 核心模組 -fs
• NodeJS 提供的核心模組 提供處理檔案系統的各種方法,透過 require(‘fs’)載入 重要的功能
fs.open(path, flag, mode, callback): 開啟檔案, fd 會在開啟檔案後傳遞給 callback
fs.read(fd, buffer, offset, length, position, [callback]): 讀取檔案 fs.write(fd, buffer, offset, length, position, [callback]): 寫入檔案 fs.readFile(filename, [encoding], [callback]): 一次讀取整個檔案 fs.close(fd): 關閉檔案還有一些目錄及檔案操作的函數
開發 NodeJS 程式 核心模組 -net
• NodeJS 提供的核心模組 網路操作的各種方法,透過 require(‘net’)載入 重要的功能
net.createServer([opt], connectionListener): 產生 net.Server物件,並且把 connectionListener設定為’ connection’ 事件處理函數,將 net.Socket物件傳給它
net.createConnection(port or fd…, [callback]): 產生net.Socket物件,並且把 callback設定為’ connection’ 事件處理函數,將 netSocket物件傳給它
開發 NodeJS 程式 核心模組 -net
• NodeJS 提供的核心模組 網路操作的各種方法,透過 require(‘net’)載入 重要的功能
net.Server server.listen(): 監聽 port或是 fd server.close(): 關閉網路連接 server.pause(): 暫停 connection 事件:會在網路連接建立時觸發,把 net.Socket物件傳遞給事件處理函數做進一步處理
開發 NodeJS 程式 核心模組 -net
• NodeJS 提供的核心模組 網路操作的各種方法,透過 require(‘net’)載入 重要的功能
net.Socket connect 事件:在 socket連結建立時觸發 data 事件 : 在 socket收到資料時觸發 connect(port or fd): 建立網路 port或 fd 與 socket 的繫結 setEncoding(encoding): 指定資料編碼格式 ex. utf8, ascii,
base64 write(data): 將資料寫入 socket送出 address(): 取得本地監聽的 ip 及 port 資料 remoteAddress/remotePort: 取得遠端的網址 /port
開發 NodeJS 程式 核心模組 -net
• NodeJS 提供的核心模組 網路操作的各種方法,透過 require(‘net’)載入 使用說明
客戶端每次建立一個連線,就會觸發 connection 事件透過傳遞給 connection 事件處理函數的 net.Socket物件,就可
以接收資料 /傳遞資料 net 模組可以用來建立各種 tcp 伺服器
開發 NodeJS 程式 核心模組 -http
• NodeJS 提供的核心模組建立 http 伺服器,透過 require(‘http’)載入 使用說明
http.createServer(requestListener): 通常只要使用這個方法 request 事件 : 會在使用者對伺服器請求時觸發,會傳入
ServerRequest, ServerReponse物件給處理函數
開發 NodeJS 程式 核心模組 -http
• NodeJS 提供的核心模組建立 http 伺服器,透過 require(‘http’)載入 使用說明
ServerRequest request.url: 使用者 request 的網址 request.method: http method ,例如 GET, POST等 request.headers: request header陣列 data 事件 : 在 request body 資料收到後觸發
開發 NodeJS 程式 核心模組 -http
• NodeJS 提供的核心模組建立 http 伺服器,透過 require(‘http’)載入 使用說明
ServerResponse writeHead(status, [reasonPhrase], [headers]): 將 http狀態及
header回覆給 client write(chuck, encoding): 將部份資料回覆給 client end(data, encoding): 類似 write ,不過在回覆資料後就結束連結
開發 NodeJS 程式 核心模組 -url
• NodeJS 提供的核心模組協助剖析網址,透過 require(‘url’)載入 使用說明
url.parse(urlString, parseQueryString=false, slashDenoteHost=false): 剖析網址,回傳包含 URL各個組成部分的物件。 parseQueryString指定是否要剖析網址之後的query string。最後一個參數指定是否要把 //host/path 剖析成{host: ‘host’, path: ‘path’}
開發 NodeJS 程式 核心模組 -vm
• NodeJS 提供的核心模組編譯執行 Javascript ,透過 require(‘vm’)載入 使用說明
vm.runInThisContext(code, [filename]): 在目前的 context 中編譯執行 code字串,如果指定了 filename ,會調整 process 中的資訊( script 檔名等)
vm.runInNewContext(code, [sandbox], [filename]): 在新的context 中執行 code ,如果指定 sandbox物件,則把它當作context
開發 NodeJS 程式 核心模組 -child process
• NodeJS 提供的核心模組 提供建立子行程的功能,透過 require(‘child_process’)載入。這部份功能在 windows 上的支援仍然不完整
使用說明(用不同方式執行可執行的程式,並取得其 stdio) child_process.spawn() child_process.exec() child_process.fork()
發想並撰寫一個可以與檔案系統對應的http伺服器
程式碼範例
簡單的範例 驗證概念• 嘗試讓 http server對應到檔案系統• 構想
• 從最簡單的 http server範例開始• 利用 fs 模組讀取檔案內容• 輸出到 server response
• 範例: myweb-v0.0.1.js
簡單的範例 為模組化做準備• 調整程式,把需要的操作用物件包裝,然後用建構函數來產生物
件• 只要把這個建構函數 expose ,就可以使用• 如果需要單元測試,模組化會比較方便• 範例: myweb-v0.0.2.js
簡單的範例 加上 mime 功能• server response 需要提供 mime type ,瀏覽器才有辦法知道怎樣使用
• 利用已經有人建構好的 mime 模組• 範例: myweb-v0.0.3.js
簡單的範例 提供預設檔案功能• 構想:如果 request 的資源是目錄,則在目錄中尋找
index.html 檔案,輸出到 server response• 範例: myweb-v0.0.4.js
簡單的範例 模組化• 構想:
• 利用 module.exports輸出MyHttpServer建構函數• 使用時透過 new 來建立實體
• 範例: myweb-v0.0.5.js, test-v0.0.5.js
簡單的範例 嘗試使用 process.nextTick改進效能• 構想:
• 一些流程利用匿名函數包裝,丟給 process.nextTick 非同步執行• 不過實測對於效能並沒有明顯改進
• 範例: myweb-v0.0.6.js, test-v0.0.6.js
簡單的範例 加上靜態檔案 cache改進效能• 構想:
把靜態檔案存入 cache ,如果有 cache就直接使用,減少 I/O測試過,對於效能有明顯提昇
• 範例: myweb-v0.0.7.js, test-v0.0.7.js
簡單的範例 加上 router 機制,讓網址對應到處理函數• 構想:
• 模仿 express framework ,利用 get(‘path’, func) 來新增利用GET 方法,請求 path 路徑的處理函數 func
• post, put, delete, head等也可以使用同樣方法• 範例: myweb-v0.0.8.js, test-v0.0.8.js
簡單的範例 開始做架構調整,先加上 cookie 機制• 構想:
利用 NodeJS 的事件機制,在伺服器每個 request 的 life cycle 中,插入 hook函數
利用 nodeunit做單元測試,以確保架構調整沒有問題加上’ init’ hook ,並且在這個階段處理 cookie hook函數,會接收到 request 與 response物件做處理
• 範例: myweb-v0.0.9.js, test-v0.0.9.js
目前的支援狀況還有與 iis整合的方式Windows環境?
NodeJS 在 Windows 中的支援
• v0.6.0 前預設要完成的目標(綠色為已完成)支援 IOCP(透過 libuv)支援使用 Visual C++編譯支援 Named Pipe ( 類似 Unix Domain Socket)支援 child process支援動態的原生模組 (dll 格式 )編譯成 64位元執行檔 其他… (還很多 )
NodeJS 在 Windows 中的支援
• 目前最新開發版: v0.5.6 有 219 個測試通過, 38 個測試失敗,早幾版的數字大致相反
不需調整,就可以用 VC++編譯,之前版本不行持續改進 child process支援(完整支援據說還要一兩個月)持續改進修正 crypt 與 https 的問題
與 IIS整合 介紹 iisnode
• 下載及安裝,參考網站中的指引:https://github.com/tjanczuk/iisnode
• 設定 web.config ,為要執行的 NodeJS 程式指定 Handler• 只支援 http協定• 原理:
• 把 IIS 當作 proxy ,利用 named pipe把 request/response導到執行的 NodeJS instance
• 伺服器程式要改寫,監聽 process.env.PORT , IIS 會透過這個環境變數,把 named pipe 路徑傳給 NodeJS
• 可以透過設定,自動做負載均衡• 效能不到直接執行 NodeJS 的一半,但是可以很方便做
proxy 與負載均衡
Q & A
一些資源• http://nodejs.org • http://npmjs.org • http://howtonode.org• http://groups.google.com/group/nodejs• http://www.facebook.com/NodeJS.tw• http://wiki.nodejs.tw• https://github.com/tjanczuk/iisnode