Email me: jollen # jollen.org

more: Jollen 的 Embedded Linux 教育訓練

« February 2014 | (回到Blog入口) | June 2014 »

April 2014 歸檔

April 15, 2014

我用 Markdown 語法

過去,我的文章大多以純文字方式撰寫,技術筆記也是。大部份的文章與筆記,都會整理到部落格和大家分享。我的部落格後台是採用 MovableType 這個古老的系統,因為一些原因(個人的一些特殊喜好),所以至今仍使用這套軟體。不管是 WordPress 或 MovableType,都需要登入後台,並且還要以 HTML 標籤語法來加工文章。

這一年多因為工作習慣的改變,以及使用網路習慣的改變,登入後台更新文章並不方便,加上還要處理 HTML 的加工,所以就不常更新部落格了。文章就靜靜地躺在我的硬碟裡。

直到去年,我開始使用 Markdown 語法來整理這些文字,原因是,希望將整理過的文字,批次出版成 E-book。Markdown 語法自然成為最佳方案之一。自助出版平臺,例如:Leanpub,都能支援 Markdown 格式。利用 Pandoc 也能將 Markdown 製作成簡報,非常方便。

將 Markdown 再轉為 HTML 雖然很簡單,但又要多做一個工。不如把 Markdown 內文,直接貼到部落格就好:加上一段「Client-side Markdown Parsing」的程式碼即可一勞永逸。

Markdown 語法真是打遍天下,不管是編修 Wiki,或是撰寫 Github 專案的說明,還是在 Github issues 裡貼文,都難不到。

Node.js 入門, #1:Hello World

本文章採用 Markdown 語法撰寫(why?),若無法閱讀內文,請點擊這裡。

Node.js 入門, #1:Hello World

Node.js 並不是使用於 Client-side,它使用於 Server-side。有關 Node.js 的說明,可參考 Node.js 官方網站。在繼續進行範例說明前,請先備妥這份文件:

http://nodejs.org/api/

另外,也請參考 Node.js 官方網站的說明,來安裝 Node.js 環境。關於環境安裝,以及 Node.js 的入門觀念,可參考由 MokoVersity 所提供的免費線上課程:

http://www.mokoversity.com/course/html5/nodejs-overview

取得範例

本文所撰寫的 Node.js 程式碼,皆可在 Github 上取得:

https://github.com/jollen/html5-websocket-nodejs

接下來,讓我們用一個連貫性的實例:即時通訊軟體,來為大家介紹 Node.js 技術。

第一個 Node.js 程式

Node.js 能提供 Web Server 的能力。所以,不免俗地先了解 "Hello, World" 的寫法:

// 01-create-server/hello.js
 1 var http = require('http');
 2 
 3 var httpServer = http.createServer(function (req, res) {
 4   res.writeHead(200, {'Content-Type': 'text/html'});
 5   res.end('<h1>Hello World</h1>\n');
 6 });
 7 
 8 httpServer.listen(8080);
 9 
10 console.log('Server running at http://127.0.0.1:8080/');

程式碼第 3 行的地方,呼叫 http 模組的 createServer() 函數來建立一個 Web Server 物件。建立 Web Server 物件,並且啟動一個 Web Server,是 Node.js 技術的第一個步驟。

createServer()函數的說明如下:

http.createServer([requestListener])

createServer() 執行成功後傳回 Web Server 物件,參數 requestListener 是一個 Request Handler Function,用來處理 request 事件。關於 Node.js 的事件處理技術,後續再做說明。當 request 事件發生時,Request Handler Function 將被 Callback,並帶有二個參數:

  • req:http.ServerRequest的實例化(instance)
  • res:http.ServerResponse的實例化

將上述的範例,儲存為 hello.js,並且利用 node 指令執行:

$ node hello.js

安裝 Node.js 後,就可以取得 node 命令。

這是執行 Node.js 程式碼的陽春版做法,後續將導入 forever 工具,以進階的方式來執行 Node.js 程式。

Node.js 採用 Google 所開發的 V8 JavaScript 引擎,原本 V8 引擎是設計給瀏覽器使用的 JavaScript 引擎,現在有開發者把它抽離出來,變成一個獨立的直譯器,讓 JavaScript 程式碼升格為 Server-Side Script。

我們利用瀏覽器連到 http://127.0.0.1:1234/。

V8 JavaScript引擎介紹

JavaScript 引擎將成為手持裝置的重要技術。早期的 Android 系統,使用的 JavaScript 引擎稱為 JavaScriptCore (JSC),這是由 Apple 所開發的 JavaScript 引擎,並且包含在 Webkit 中。因為一些原因,Google 也決定開發自已的 JavaScript 引擎,稱之為 V8。

技術上,JSC 與 V8 的設計理念不同,一般相信,新一代的 V8 引擎效能比 JSC 引擎更好。Android 2.3 加入了 V8 引擎,若想使用最近的 V8 引擎,就要使用 Android 2.3 以上的版本。

為什麼要使用 Node.js?

到這裡,大家可能會有一個疑問。為什麼不使用現有的 Web Server 來開發 Web Service 就好,例如使用 Apache。非要使用 Node.js 技術不可嗎?這個問題的答案,要從 Thread Model 說起。

典型的 Web Server 以 Multi-thread 架構來實作「Concurrency」,也就是以建立 Thread 的方式,來處理處理事件(Events)。但是過多的 Thread 會造成伺服器的負擔:

  • 假設一個 Thread 可以處理 10 個事件
  • 同時處理 1000 個事件,就必須建立 100 個 Thread
  • 大量的 Thread 在分時作業系統裡,會造成 Context-Switch Overhead,讓每一個 Thread 處理事件的時間拉長,形成效能低落的現象

由此可知:

  • 若是將 Multi-thread 架構,應用在「處理巨量的同時連線請求」上,伺服器的負擔就會很大
  • Multi-thread 架構的軟體,可能在系統產生過多的 Thread,過多的 Thread 除造成伺服器的負載增加外,也需要大量的記憶體

是否有替代方案呢?將上述的 Multi-thread 架構,改為 Event Loop 架構即可。Node.js 的訴求之一就是:採用 Event Loop 架構。此外,Node.js 採用 JavaScript 程式語言,JavaScript 本身也有一些很好的語言特性:

  • 具備 Lambda 運算子,大量使用暱名函數(anonymous function)與 Closure(封閉性)觀念
  • 使用 Callback Object 做為函數的參數(Lambda),易於處理 Non-blocking Operation 與 Event Handling

Node.js 本身的 I/O 操作,也大多是(幾乎)Non-blocking 的機制。這點與 PHP 有很大的不同。這樣的機制,對於消化巨量的連線請求,有非常大的幫助。

Node.js 入門, #2:Node.js 模組

本文章採用 Markdown 語法撰寫(why?),若無法閱讀內文,請點擊這裡。

製作 Node.js 模組

學習 Node.js 的第一件事情,就是了解如何將程式碼模組化,簡單來說,就是製作一個程式庫 Node.js 的模組隱含著 Closure 的特性。

JavaScript 比較講求模組化,所以我們重構 hello.js。先將 Web Server 的部份獨立成一個模組,程式碼規劃如下:

  • index.js:主程式
  • server.js:啟動Web server的模組

index.js的完整程式碼如下:

// 02-modules/hello.js
var server = require("./server");

server.start();

主程式的部份,以 require() 函數將 server 模組(即 server.js 檔案)引入,接著呼叫模組裡的 start() 函數。server.js 完整程式碼如下:

// 02-modules/server.js
 1 var http = require("http");
 2 
 3 function start() {
 4   function onRequest(request, response) {
 5     console.log("Request for " + pathname + " received.");
 6 
 7     response.writeHead(200, {"Content-Type": "text/plain"});
 8     response.write("Hello World");
 9     response.end();
10   }
11 
12   http.createServer(onRequest).listen(8080);
13   console.log("Server has started.");
14 }
15 
16 // Export functions
17 exports.start = start;

程式碼第 3 行到第 16 行的地方,我們實作了一個函數,並且將它匯出。請特別留意,沒有匯出的函數,將不是 Public,它不能被外部的人呼叫。exports 是 Node.js 的一個 Global object,用來讓我們匯出模組裡的函數,成為 Public Function。

目前為止,我們發現了一些觀念:

  • Frontend 與 Backend 都使用 JavaScript 做為主要的程式語言
  • Frontend 與 Backend 都要模組化,並引入 Closure 觀念
  • Frontend 與 Backend 的 Module / Closure,相念相通,實作方式不同

Chaining Pattern

另外,server.js 裡也做了一些改寫。程式碼第 4 行的地方,以具名函數的方式重新實作,目的是讓程式碼更具可維護性。此外,程式碼第 14 行的地方:

http.createServer(onRequest).listen(8080);

物件接著下一個物件來連續呼叫多個方法的寫法,就叫 Chaining Pattern(鏈接模式)。這個設計模式的目的,同樣是為了提升程式碼的可維護性:不但能簡化程式碼,更能讓程式碼能構成一個句子。

在接下來的範例裡,我們將善用具名函數以及 Chaining Pattern 來提昇程式碼的可維護性。

關於 April 2014

此頁面包含了在April 2014發表於Jollen's Blog的所有日記,它們從老到新列出。

前一個存檔 February 2014。

後一個存檔 June 2014。

更多信息可在 主索引 頁和 歸檔 頁看到。

Top | 授權條款 | Jollen's Forum: Blog 評論、討論與搜尋
Copyright(c) 2006 www.jollen.org