All about NodeJS

3,901 views
3,780 views

Published on

Published in: Technology
0 Comments
17 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,901
On SlideShare
0
From Embeds
0
Number of Embeds
546
Actions
Shares
0
Downloads
118
Comments
0
Likes
17
Embeds 0
No embeds

No notes for slide

All about NodeJS

  1. 1. 瞭解NodeJS開發技術<br />by Fillano<br />
  2. 2. 課程主要內容<br />NodeJS的背景知識<br />如何撰寫NodeJS程式<br />幾個codeexample展示與說明<br />在Windows環境中執行NodeJS<br />如何找到更多資源<br />
  3. 3. NodeJS的背景知識<br />作者、Javascript、V8及其它<br />
  4. 4. 什麼是NodeJS<br />它主要是一個伺服器端的Javascript環境<br />它提供了符合CommonJS1.0規格的模組機制,擴充功能非方便<br />只要能使用模組來擴充功能,實際使用上並不限於伺服器程式<br />
  5. 5. 什麼是NodeJS<br />舊瓶裝新酒<br />1996–NetscapeLivewireinNetscapeEnterpriseServer<br />ASPwithJscript,Jscript.NET<br />MozillaRhino<br />Flowscript for Apache Cocoon 2.1<br />JavascriptWebflow for Spring<br />Helma (http://helma.org)<br />RingoJS(http://ringojs.org/)<br />
  6. 6. 什麼是NodeJS<br />舊瓶裝新酒<br />MozillaSpiderMonkey<br />AptanaJaxer(http://jaxer.org/)<br />couchDB (RESTful API)<br />GoogleV8<br />v8cgi(http://code.google.com/p/v8cgi/)<br />v8juice(http://code.google.com/p/v8-juice/)<br />wikipedia: Comparison of server-side JavaScript solutions<br />
  7. 7. 什麼是NodeJS<br />全新的生命力<br /><ul><li>不需要倚賴其他伺服器
  8. 8. 類似v8juice與jslib(http://jslib.mozdev.org/)
  9. 9. 接下來會談到的成功因素</li></li></ul><li>為什麼這麼熱門<br />因為執行速度非常快<br />有多快?一些比較:<br /><ul><li>http://shootout.alioth.debian.org/
  10. 10. vsphp (benchmarking nodejs basic performance tests against apache-php)
  11. 11. vsruby(express vs sinatra benchmarks)
  12. 12. vsringojs(RingoJS vs. Node.js: Runtime Values)</li></li></ul><li>為什麼它這麼快?<br />它使用了GoogleV8Javascript 引擎<br /><ul><li>特別的JIT技術:兩階段JIT
  13. 13. AST:將Javascript剖析成抽象語法樹
  14. 14. GenericCodeGen:直接產生尚未最佳化的機器碼執行
  15. 15. 目前使用的最佳化技術Cranshaft
  16. 16. 執行時期追蹤與Profiling
  17. 17. 將型別資訊紀錄在相關AST節點中
  18. 18. OptimizedCodeGen
  19. 19. 四階段最佳化,產生可利用暫存器存放變數的機器碼</li></li></ul><li>為什麼它這麼快?<br />EventedI/O<br /><ul><li>I/O的速度,遠比CPU執行的速度慢,所以最有效率的方法是在I/O完成時,由系統通知程式執行完畢,可以處理I/O動作執行的結果</li></li></ul><li>為什麼它這麼快?<br />EventedI/O<br /><ul><li>舊方法:select,poll,需要用兩個很慢的方法來監視資源
  20. 20. 輪詢:每隔一段時間詢問系統是否有結果
  21. 21. 遍歷:走訪每一個要監聽的檔案與網路port</li></li></ul><li>為什麼它這麼快?<br />EventedI/O<br /><ul><li>新方法:eventedI/O,告訴系統要監控的資源,當有變動時,系統以事件通知
  22. 22. Linux:epoll
  23. 23. BSD:kqueue
  24. 24. Windows, Solaris:IOCP (I/O Completion Port)</li></li></ul><li>誰創造了NodeJSRyanDahl<br />在德國工作的美籍Freelancer,專長:<br /><ul><li>InterruptableParser
  25. 25. Eventloops(event-machine, gearman…)
  26. 26. Responsetimehistorgram</li></li></ul><li>誰創造了NodeJSRyanDahl<br />一些開放原始碼專案的發起者:<br /><ul><li>Ebb web server
  27. 27. EY Load Balancer module for Nginx</li></li></ul><li>誰創造了NodeJSRyanDahl<br />為了解決網站伺服器效能的問題,嘗試了:<br /><ul><li>Ruby:EventMachine
  28. 28. Python:Twisted</li></ul>但是都不能滿意,在GoogleV8Engine發表後,決定自己寫一個:<br /><ul><li>2009JSConf發表,獲得全場起立鼓掌
  29. 29. Crockford曾說:這是Javascript發展過程的一個重要案例,會影響未來ECMA-262規格的制定</li></li></ul><li>誰創造了NodeJSIssacSchlueter及其它開發者<br />IssacSchlueter:NodeJS上最多人使用的套件管理系統-NPM的作者,目前是RyanDahl在Joyent的同事<br />更多貢獻者:<br />BertBelder(Releasemanager),TimCaswell(Howtonodewebsite),FelixGeisendorfer,TJHollowaychuck(ExpressFramework), PaulQuerna,MattRanney,MikealRogers,MicheilSmithetc…<br />
  30. 30. 哪裡可以找到NodeJS<br />http://nodejs.org<br /><ul><li>最新版本的原始碼檔案下載
  31. 31. 最新版本的Windows可執行檔下載
  32. 32. 最新版本的API文件</li></ul>http://github.com/joynet/node<br /><ul><li>原始碼 Repository
  33. 33. wiki:重點-如何在不同作業系統中編譯NodeJS
  34. 34. IssueTracker</li></li></ul><li>誰在使用NodeJS<br />Plurk(www.plurk.com)<br /><ul><li>http://www.slideshare.net/amix3k/comet-with-nodejs-and-v8</li></ul>Linkedin(www.linkedin.com)<br /><ul><li>How LinkedIn used Node.js and HTML5 to build a better, faster app</li></ul>其它,參考:<br /><ul><li>Projects, Applications, and Companies Using Node
  35. 35. (列表中有一些是提供NodeJSHosting服務的公司,他們自己也利用NodeJS開發相關管理方案,例如nodejitsu)</li></li></ul><li>使用NodeJS的時機快速反應!<br />可以但並不適用於所有案例<br />重點:當快速反應是最重要考量時<br />並不適合需要大量運算的案例<br />
  36. 36. 使用NodeJS的時機快速反應!<br />單一執行緒與eventloop<br /><ul><li>Javascript程式本身只能在一個執行緒中執行
  37. 37. 所有事件都是在一個eventloop依序執行
  38. 38. 所以反應速度還是會隨著連線數上昇而逐漸下降</li></ul>解決方法<br /><ul><li>在單一或多個機器上同時執行多個nodeinstance,使用proxy做loadbalance
  39. 39. 新版的V8引擎可以支援一個行程多個instance</li></li></ul><li>當前開發狀態<br />v0.5x(開發版)<br /><ul><li>支援MicrosoftWindows
  40. 40. 支援child_process
  41. 41. 支援IOCP
  42. 42. 可動態載入的原生模組
  43. 43. 其它
  44. 44. 支援VisualC++
  45. 45. 之前只能在Cygwin及MSYS環境中編譯
  46. 46. v0.5.6將可以在VisualC++Express正確編譯</li></li></ul><li>當前開發狀態<br />關鍵:libuv<br /><ul><li>支援不同OS的eventedI/O抽象層
  47. 47. 支援MicrosoftWindows的I/OCompletionPort機制
  48. 48. 讓NodeJS抽換掉對於libeio,libevent,libev等的直接依賴
  49. 49. 在Windows環境中可使用VisualC++編譯</li></li></ul><li>如何撰寫NodeJS程式<br />Javascript知識、效能、NodeJS開發環境<br />
  50. 50. 最簡單的程式範例helloworld伺服器<br />一頁就放的下的程式<br />var http = require('http');<br />http.createServer(function(req, res) {<br />res.writeHead(200, {'Content-Type': 'text/plain'});<br />res.end('Hello World.');<br />}).listen(1337, "127.0.0.1");<br />console.log('Server running at http://127.0.0.1:1337/');<br />
  51. 51. 最簡單的程式範例helloworld加上ExpressFramework<br />一頁就放的下的程式<br />var express = reuqire('express'),<br />app=express.createServer();<br />app.get('/',function(req,res){<br />res.send('Hello World.');<br />});<br />app.listen(3000);<br />
  52. 52. Javascript背景知識伺服器端的Javascript<br />與瀏覽器中有什麼不同?<br /><ul><li>沒有DOM物件
  53. 53. Global提供的環境不一樣</li></ul>其它地方大同小異<br /><ul><li>因為都是Javascript(ECMAScript)
  54. 54. 以NodeJS來說,大量使用非同步的執行方式,但是與在瀏覽器中事件與非同步的寫法也差不多</li></li></ul><li>Javascript背景知識eventloop<br />
  55. 55. Javascript背景知識eventloop<br />Javascript程式的LifeCycle<br /><ul><li>第一步先執行GlobalContext中的程式碼
  56. 56. 接下來,用eventloop的方式執行所有事件函數,直到結束
  57. 57. 如果在瀏覽器中,可以利用動態新增script tag的方式,再次執行載入的script中GlobalContext中的程式碼,不過在NodeJS不會有這個狀況發生
  58. 58. 所以,大部份時間可能都是在執行函數</li></li></ul><li>Javascript背景知識event loop<br />優點<br /><ul><li>沒有執行緒的額外負擔,反應速度快
  59. 59. 共用的變數不需鎖定,程式結構簡單</li></ul>缺點<br /><ul><li>某一函數執行時間長,就會推遲其它函數執行
  60. 60. 無法把負載分散到不同的CPU</li></ul>解決方法(以NodeJS為例)<br /><ul><li>同時執行多個instance,利用proxy做負載均衡
  61. 61. Intel的計畫,讓Javascript可以在多核心環境中進行平行處理
  62. 62. https://github.com/RiverTrail/RiverTrail
  63. 63. 目前只支援Firefox</li></li></ul><li>Javascript背景知識事件與callback函數<br />通常在使用事件時,會傳遞給它一個函數,利用這個函數來執行事件觸發時要職行的動作,這個函數就叫做callback函數<br />varelem=document.getElementById(‘target’);<br />elem.addEventListener(‘click’,function(e){<br />//thisisacallbackfunction<br />},false);<br />
  64. 64. Javascript背景知識事件與callback函數<br />在瀏覽器中,通常很少超過兩層<br />varelem=document.getElementById(‘target’);<br />elem.addEventListener(‘click’,function(e){<br />req.onreadystatechange=function(){<br /> if(this.readyState===4&&this.status===200){<br />varthat=this;<br />window.setTimeout(function(){<br /> alert(that.responseTest)<br /> },500)<br /> }<br />}<br />},false);<br />
  65. 65. Javascript背景知識事件與callback函數<br />在NodeJS環境中,有非常多的操作是用callback來完成,例如這一段mongo db的範例<br />varp_client = new Db('integration_tests_20', new Server("127.0.0.1", 27017, {}), {'pk':CustomPKFactory});<br />p_client.open(function(err, p_client) {<br />p_client.dropDatabase(function(err, done) {<br />p_client.createCollection('test_custom_key', function(err, collection) {<br />collection.insert({'a':1}, function(err, docs) {<br />collection.find({'_id':newObjectID("aaaaaaaaaaaa")}, function(err, cursor) {<br />cursor.toArray(function(err, items) {<br />test.assertEquals(1, items.length);<br />p_client.close();<br />});});});});});});<br />
  66. 66. Javascript背景知識事件與callback函數<br />為什麼會出現這麼多層的callbacks?<br /><ul><li>重要的操作幾乎都透過callback已非同步的方式完成
  67. 67. 所以常常在callbacks中使用其他功能,就需要另外加一層callbacks
  68. 68. 在許多功能需要循序執行時,就需要在callbacks中使用下一個步驟的功能,這些還是需要callbacks來完成</li></li></ul><li>Javascript背景知識事件與callback函數<br />複雜callbacks的問題<br /><ul><li>程式邏輯會分散到各個callbacks,比較難除錯
  69. 69. 不容易做單元測試</li></ul>解決方式<br /><ul><li>借助一些模組的幫助,將這些非同步的callbacks改成同步的形式(底層還是使用非同步)
  70. 70. 不要用匿名函數做callbacks,這樣對它做單元測試就比較容易</li></li></ul><li>Javascript背景知識撰寫Javascript程式的一些原則<br />不要污染Global Scope<br /><ul><li>利用Object把函數及變數Group起來(namespacing)
  71. 71. 利用立即執行的匿名函數,把在Global Scope執行的程式包裝起來
  72. 72. 不過只要好好使用模組,在NodeJS這不是大問題</li></ul>簡單的性能策略<br /><ul><li>注意變數Scope解析的問題
  73. 73. 需要花時間處理的程式,可以切割成數個函數,利用process.nextTick()非同步執行</li></li></ul><li>V8 Javascript VM的性能一些簡單的原則<br />V8會依照函數執行的次數作為參考,進行最佳化(hot functions)<br /><ul><li>某個函數預期它會在NodeJS instance生命週期中執行越多次,調整它對於效能就會更有效果
  74. 74. 某些操作在Javascript中並沒有非同步執行的版本,例如JSON.parse/stringify,而這些操作比較花時間。這時可以找一找是否有人實作非同步的版本(模組)
  75. 75. 例如: https://github.com/dominictarr/JSONStream</li></li></ul><li>V8 Javascript VM的性能一些簡單的原則<br />但是有一些地方會妨礙V8做最佳化<br /><ul><li>無法決定scope中變數的型別時
  76. 76. 某些Javascript函數,無法最佳化,所以使用到的話…
  77. 77. 例如:用Array.prototype.slice.call(arguments,1)來把arguments轉換成陣列就比for(var i=0; i<arguments.length; i++)慢,因為後者可以最佳化</li></li></ul><li>開發NodeJS程式環境建置<br />取得NodeJS可執行檔<br /><ul><li>Unix-Like環境
  78. 78. 需要預先安裝Python及GCC4.0以上
  79. 79. 在nodejs.org網站取得原始碼
  80. 80. 解開後依序執行./configure、make
  81. 81. 需要安裝到系統中時,執行make install</li></li></ul><li>開發NodeJS程式環境建制<br />取得NodeJS可執行檔<br /><ul><li>Windows環境
  82. 82. 安裝Cygwin或是mingw+msys環境,還是需要Python及GCC4.0以上
  83. 83. 解開後依序執行./configure、make
  84. 84. 需要安裝到系統中時,執行make install
  85. 85. 如果需要在純windows環境中執行node.exe,還需要把Cygwin或是msys提供的一些dll檔複製到同一個目錄
  86. 86. 如果不知道要複製哪些,執行node.exe會出現找不到這些dll檔的錯誤訊息,可以當作參考</li></li></ul><li>開發NodeJS程式環境建制<br />取得NodeJS可執行檔<br /><ul><li>Windows環境
  87. 87. V0.5.6之後,可以直接使用Microsoft Visual C++ 2010來編譯,不過這個開發版本尚未釋出
  88. 88. 不想自己編譯的話,V0.5.x都有提供已編譯好的執行檔</li></li></ul><li>開發NodeJS程式環境建制<br />安裝NPM(node package manager)<br /><ul><li>Unix-like環境
  89. 89. 需要預先安裝curl
  90. 90. 參考npmjs.org首頁上提供的方式,執行one line install
  91. 91. Windows環境
  92. 92. 目前在Windows環境中還無法執行npm
  93. 93. 但是可利用NODE_PATH環境變數指定模組的預設路徑
  94. 94. 到search.npmjs.org網站上尋找要安裝的模組
  95. 95. 參考依賴性,把相關的模組一起安裝到NODE_PATH</li></li></ul><li>開發NodeJS程式Global Scope環境<br />Javascript的運行環境是由host透過存在於Global Scope的物件或函數來提供的例如在node.exe的console中執行以下程式,就可以列舉出Global Scope中的物件與函數<br />> (function(o){for(var i in o) console.log(i)})(this);<br />
  96. 96. 開發NodeJS程式Global Scope環境<br />結果可以看到:<br />> (function(o){for(var i in o) console.log(i)})(this);<br />ArrayBuffer<br />Int8Array<br />Uint8Array<br />Int16Array<br />Uint16Array<br />Int32Array<br />Uint32Array<br />Float32Array<br />Float64Array<br />DataView<br />global<br />……<br />TypedArray相關物件<br />Global物件的別名,就像瀏覽器環境中的window物件<br />
  97. 97. 開發NodeJS程式Global Scope環境<br />結果可以看到:<br />…<br />process<br />GLOBAL<br />root<br />Buffer<br />setTimeout<br />setInterval<br />clearTimeout<br />clearInterval<br />console<br />處理行程的物件,有行程相關資訊、取得工作目錄等功能<br />Global物件的別名,就像瀏覽器環境中的window物件<br />用來處理binary資料的物件<br />跟瀏覽器中的一樣啦<br />用來做stdio的物件,可以輸出錯誤、debug、log等資訊<br />
  98. 98. 開發NodeJS程式Global Scope環境<br />還漏掉一些(不會列舉出來):<br />…<br />__dirname<br />__pathname<br />exports<br />module<br />程式所在目錄的絕對路徑<br />所執行js檔案的絕對路徑<br />撰寫模組時,用來將介面輸出到呼叫端的物件<br />其實就是module.exports<br />提供目前模組的功能介面與資訊<br />如果撰寫「模組」,這幾個顯示的都是模組「local」的資訊<br />
  99. 99. 開發NodeJS程式核心模組<br />核心模組是編譯在NodeJS執行檔中的模組<br />與外部模組一樣,透過下面方式載入使用<br />var http = require(‘http’);//將http模組載入,指派給http變數<br />var server = http.createServer(function(request, response) {<br />//分析request資訊,寫入response<br />});<br />server.listen(80, ‘127.0.0.1’);<br />
  100. 100. 開發NodeJS程式核心模組-console (STDIO)<br />NodeJS提供的核心模組<br /><ul><li>提供標準輸入輸出功能,會自動載入
  101. 101. 重要的功能:
  102. 102. console.log()/console.info(): 輸出訊息到標準輸出
  103. 103. console.warn()/console.error(): 輸出訊息到標準錯誤
  104. 104. console.dir(物件): 把物件資訊輸出到標準錯誤
  105. 105. console.trace(): 傾印程式當前位置的stack trace資訊
  106. 106. console.assert(): 就是assert.ok(),用來做測試</li></li></ul><li>開發NodeJS程式核心模組-timers<br />NodeJS提供的核心模組<br /><ul><li>會自動載入
  107. 107. 重要的功能(跟瀏覽器中的一樣)
  108. 108. setTimeout(callback, time)
  109. 109. clearTimeout(tid)
  110. 110. setInterval(callback, time)
  111. 111. clearInterval(tid)</li></li></ul><li>開發NodeJS程式核心模組-process<br />NodeJS提供的核心模組<br /><ul><li>提供行程資訊與操作,會自動載入
  112. 112. 重要的功能
  113. 113. process.stdout / stderr: 寫入標準輸出/標準錯誤的writeable stream物件
  114. 114. process.stdin: 讀取標準輸入的readable stream物件
  115. 115. process.argv: 程式啟動時傳入的參數
  116. 116. process.env: 取得系統環境變數
  117. 117. process.nextTick(callback): 讓callback非同步執行
  118. 118. process.cwd() / chdir(): 取得/修改目前工作目錄
  119. 119. process.exit(code=0): 結束行程,返回訊息代碼</li></li></ul><li>開發NodeJS程式核心模組-util<br />NodeJS提供的核心模組<br /><ul><li>提供一些常用的工具函數,使用require(‘util’)載入
  120. 120. 重要的功能
  121. 121. util.format(): 返回格式化字串
  122. 122. util.debug(string): 輸出訊息到標準錯誤,執行時會停止所有程式
  123. 123. util.log(string): 輸出訊息到標準輸出,並加上時間資訊
  124. 124. util.inspect(object): 回傳物件的代表資訊
  125. 125. util.pump(readableStream, writeableStream): 將讀入直接轉到寫出
  126. 126. util.inherits(target, parent): 讓目標物件繼承父物件</li></li></ul><li>開發NodeJS程式核心模組-events.EventEmitter<br />NodeJS提供的核心模組<br /><ul><li>提供事件機制,使用到事件都要繼承它,使用require(‘events’).EventEmitter載入
  127. 127. 重要的功能
  128. 128. emitter.on(‘event’, listener): 指定事件處理函數給特定事件
  129. 129. emitter.once(): 同上,但是函數只會執行一次
  130. 130. emitter.removeListener(‘evnet’, listener): 移除事件處理函數
  131. 131. emitter.removeAllListeners(‘evnet’): 移除指定事件的所有處理函數
  132. 132. emitter.listeners(‘event’): 返回指定事件的處理函數陣列
  133. 133. emitter.emit(‘event’, [參數1], [參數2], …): 執行指定事件的處理函數</li></li></ul><li>開發NodeJS程式核心模組-Buffer<br />NodeJS提供的核心模組<br /><ul><li>用來處理binary資料,自動載入
  134. 134. 重要的功能
  135. 135. new Buffer(): 建構子
  136. 136. buffer.write(): 將字串寫入Buffer
  137. 137. buffer.copy(): 把buffer的資料拷貝給指定的buffer物件
  138. 138. buffer.length: 取得buffer的長度
  139. 139. buffer[index]: 取得buffer索引位置的資料</li></li></ul><li>開發NodeJS程式核心模組-streams<br />NodeJS提供的核心模組<br /><ul><li>用來處理各種資料的I/O的抽象結構,通常包裝成不同物件的成員自動載入,有Readable及Writeable兩種
  140. 140. 重要的功能
  141. 141. Readable Stream
  142. 142. ‘data’ 事件: 會在資料到達時觸發
  143. 143. pipe(dest, [opt]): 可以把輸入(Readable)轉向輸出(Writeable)
  144. 144. Writeable Stream
  145. 145. write(buffer)/write(string, encoding): 將資料寫入
  146. 146. end()/end(string, encoding,)/end(buffer): 結束資料,不再寫入</li></li></ul><li>開發NodeJS程式核心模組-crypto<br />NodeJS提供的核心模組<br /><ul><li>提供處理加解密的各個方法,透過require(‘crypto’)載入
  147. 147. 重要的功能
  148. 148. createCredentials()/createHmac()/creatCipher()/createDecipher()/ createSign()/createVerify()/createDiffeHellman()等: 產生各種用來做加解密、hash、簽章、驗證等物件
  149. 149. update(data): 用來把資料傳給上述物件,可搭配stream的方式在收到資料時傳給它,最後再用各物件的個別的操作來產生結果</li></li></ul><li>開發NodeJS程式核心模組-fs<br />NodeJS提供的核心模組<br /><ul><li>提供處理檔案系統的各種方法,透過require(‘fs’)載入
  150. 150. 重要的功能
  151. 151. fs.open(path, flag, mode, callback): 開啟檔案,fd會在開啟檔案後傳遞給callback
  152. 152. fs.read(fd, buffer, offset, length, position, [callback]): 讀取檔案
  153. 153. fs.write(fd, buffer, offset, length, position, [callback]): 寫入檔案
  154. 154. fs.readFile(filename, [encoding], [callback]): 一次讀取整個檔案
  155. 155. fs.close(fd): 關閉檔案
  156. 156. 還有一些目錄及檔案操作的函數</li></li></ul><li>開發NodeJS程式核心模組-net<br />NodeJS提供的核心模組<br /><ul><li>網路操作的各種方法,透過require(‘net’)載入
  157. 157. 重要的功能
  158. 158. net.createServer([opt], connectionListener): 產生net.Server物件,並且把connectionListener設定為’connection’事件處理函數,將net.Socket物件傳給它
  159. 159. net.createConnection(port or fd…, [callback]): 產生net.Socket物件,並且把callback設定為’connection’事件處理函數,將netSocket物件傳給它</li></li></ul><li>開發NodeJS程式核心模組-net<br />NodeJS提供的核心模組<br /><ul><li>網路操作的各種方法,透過require(‘net’)載入
  160. 160. 重要的功能
  161. 161. net.Server
  162. 162. server.listen(): 監聽port或是fd
  163. 163. server.close(): 關閉網路連接
  164. 164. server.pause(): 暫停
  165. 165. connection事件:會在網路連接建立時觸發,把net.Socket物件傳遞給事件處理函數做進一步處理</li></li></ul><li>開發NodeJS程式核心模組-net<br />NodeJS提供的核心模組<br /><ul><li>網路操作的各種方法,透過require(‘net’)載入
  166. 166. 重要的功能
  167. 167. net.Socket
  168. 168. connect事件:在socket連結建立時觸發
  169. 169. data事件: 在socket收到資料時觸發
  170. 170. connect(port or fd): 建立網路port或fd與socket的繫結
  171. 171. setEncoding(encoding): 指定資料編碼格式ex. utf8, ascii, base64
  172. 172. write(data): 將資料寫入socket送出
  173. 173. address(): 取得本地監聽的ip及port資料
  174. 174. remoteAddress/remotePort: 取得遠端的網址/port</li></li></ul><li>開發NodeJS程式核心模組-net<br />NodeJS提供的核心模組<br /><ul><li>網路操作的各種方法,透過require(‘net’)載入
  175. 175. 使用說明
  176. 176. 客戶端每次建立一個連線,就會觸發connection事件
  177. 177. 透過傳遞給connection事件處理函數的net.Socket物件,就可以接收資料/傳遞資料
  178. 178. net模組可以用來建立各種tcp伺服器</li></li></ul><li>開發NodeJS程式核心模組-http<br />NodeJS提供的核心模組<br /><ul><li>建立http伺服器,透過require(‘http’)載入
  179. 179. 使用說明
  180. 180. http.createServer(requestListener): 通常只要使用這個方法
  181. 181. request事件: 會在使用者對伺服器請求時觸發,會傳入ServerRequest, ServerReponse物件給處理函數</li></li></ul><li>開發NodeJS程式核心模組-http<br />NodeJS提供的核心模組<br /><ul><li>建立http伺服器,透過require(‘http’)載入
  182. 182. 使用說明
  183. 183. ServerRequest
  184. 184. request.url: 使用者request的網址
  185. 185. request.method: http method,例如GET, POST等
  186. 186. request.headers: request header陣列
  187. 187. data事件: 在request body資料收到後觸發</li></li></ul><li>開發NodeJS程式核心模組-http<br />NodeJS提供的核心模組<br /><ul><li>建立http伺服器,透過require(‘http’)載入
  188. 188. 使用說明
  189. 189. ServerResponse
  190. 190. writeHead(status, [reasonPhrase], [headers]): 將http狀態及header回覆給client
  191. 191. write(chuck, encoding): 將部份資料回覆給client
  192. 192. end(data, encoding): 類似write,不過在回覆資料後就結束連結</li></li></ul><li>開發NodeJS程式核心模組-url<br />NodeJS提供的核心模組<br /><ul><li>協助剖析網址,透過require(‘url’)載入
  193. 193. 使用說明
  194. 194. url.parse(urlString, parseQueryString=false, slashDenoteHost=false): 剖析網址,回傳包含URL各個組成部分的物件。parseQueryString指定是否要剖析網址之後的query string。最後一個參數指定是否要把//host/path剖析成{host: ‘host’, path: ‘path’}</li></li></ul><li>開發NodeJS程式核心模組-vm<br />NodeJS提供的核心模組<br /><ul><li>編譯執行Javascript,透過require(‘vm’)載入
  195. 195. 使用說明
  196. 196. vm.runInThisContext(code, [filename]): 在目前的context中編譯執行code字串,如果指定了filename,會調整process中的資訊(script檔名等)
  197. 197. vm.runInNewContext(code, [sandbox], [filename]): 在新的context中執行code,如果指定sandbox物件,則把它當作context</li></li></ul><li>開發NodeJS程式核心模組-child process<br />NodeJS提供的核心模組<br /><ul><li>提供建立子行程的功能,透過require(‘child_process’)載入。這部份功能在windows上的支援仍然不完整
  198. 198. 使用說明(用不同方式執行可執行的程式,並取得其stdio)
  199. 199. child_process.spawn()
  200. 200. child_process.exec()
  201. 201. child_process.fork()</li></li></ul><li>程式碼範例<br />發想並撰寫一個可以與檔案系統對應的http伺服器<br />
  202. 202. 簡單的範例驗證概念<br />嘗試讓http server對應到檔案系統<br />構想<br />從最簡單的http server範例開始<br />利用fs模組讀取檔案內容<br />輸出到server response<br />範例:myweb-v0.0.1.js<br />
  203. 203. 簡單的範例為模組化做準備<br />調整程式,把需要的操作用物件包裝,然後用建構函數來產生物件<br />只要把這個建構函數expose,就可以使用<br />如果需要單元測試,模組化會比較方便<br />範例:myweb-v0.0.2.js<br />
  204. 204. 簡單的範例加上mime功能<br />server response需要提供mime type,瀏覽器才有辦法知道怎樣使用<br />利用已經有人建構好的mime模組<br />範例:myweb-v0.0.3.js<br />
  205. 205. 簡單的範例提供預設檔案功能<br />構想:如果request的資源是目錄,則在目錄中尋找index.html檔案,輸出到server response<br />範例:myweb-v0.0.4.js<br />
  206. 206. 簡單的範例模組化<br />構想:<br />利用module.exports輸出MyHttpServer建構函數<br />使用時透過new 來建立實體<br />範例:myweb-v0.0.5.js, test-v0.0.5.js<br />
  207. 207. 簡單的範例嘗試使用process.nextTick改進效能<br />構想:<br />一些流程利用匿名函數包裝,丟給process.nextTick非同步執行<br />不過實測對於效能並沒有明顯改進<br />範例:myweb-v0.0.6.js, test-v0.0.6.js<br />
  208. 208. 簡單的範例加上靜態檔案cache改進效能<br />構想:<br /><ul><li>把靜態檔案存入cache,如果有cache就直接使用,減少I/O
  209. 209. 測試過,對於效能有明顯提昇</li></ul>範例:myweb-v0.0.7.js, test-v0.0.7.js<br />
  210. 210. 簡單的範例加上router機制,讓網址對應到處理函數<br />構想:<br />模仿express framework,利用get(‘path’, func)來新增利用GET方法,請求path路徑的處理函數func<br />post, put, delete, head等也可以使用同樣方法<br />範例:myweb-v0.0.8.js, test-v0.0.8.js<br />
  211. 211. 簡單的範例開始做架構調整,先加上cookie機制<br />構想:<br /><ul><li>利用NodeJS的事件機制,在伺服器每個request的life cycle中,插入hook函數
  212. 212. 利用nodeunit做單元測試,以確保架構調整沒有問題
  213. 213. 加上’init’ hook,並且在這個階段處理cookie
  214. 214. hook函數,會接收到request與response物件做處理</li></ul>範例:myweb-v0.0.9.js, test-v0.0.9.js<br />
  215. 215. Windows環境?<br />目前的支援狀況還有與iis整合的方式<br />
  216. 216. NodeJS在Windows中的支援<br />v0.6.0前預設要完成的目標(綠色為已完成)<br /><ul><li>支援IOCP(透過libuv)
  217. 217. 支援使用Visual C++編譯
  218. 218. 支援Named Pipe(類似Unix Domain Socket)
  219. 219. 支援child process
  220. 220. 支援動態的原生模組 (dll格式)
  221. 221. 編譯成64位元執行檔
  222. 222. 其他…(還很多)</li></li></ul><li>NodeJS在Windows中的支援<br />目前最新開發版:v0.5.6<br /><ul><li>有219個測試通過,38個測試失敗,早幾版的數字大致相反
  223. 223. 不需調整,就可以用VC++編譯,之前版本不行
  224. 224. 持續改進child process支援(完整支援據說還要一兩個月)
  225. 225. 持續改進修正crypt與https的問題</li></li></ul><li>與IIS整合介紹iisnode<br />下載及安裝,參考網站中的指引:https://github.com/tjanczuk/iisnode<br />設定web.config,為要執行的NodeJS程式指定Handler<br />只支援http協定<br />原理:<br />把IIS當作proxy,利用named pipe把request/response導到執行的NodeJS instance<br />伺服器程式要改寫,監聽process.env.PORT,IIS會透過這個環境變數,把named pipe路徑傳給NodeJS<br />可以透過設定,自動做負載均衡<br />效能不到直接執行NodeJS的一半,但是可以很方便做proxy與負載均衡<br />
  226. 226. Q & A<br />
  227. 227. 一些資源<br />http://nodejs.org<br />http://npmjs.org<br />http://howtonode.org<br />http://groups.google.com/group/nodejs<br />http://www.facebook.com/NodeJS.tw<br />http://wiki.nodejs.tw<br />https://github.com/tjanczuk/iisnode<br />

×