nodejs 事件驅動
nodejs一個最大的特點就是支持事件驅動(並發)
http://www.cnblogs.com/lua5/archive/2011/02/01/1948760.html
Node.js現在非常活躍,相關生態社區已經超過Lua(基本上比較知名的功能都有nodejs模塊實現)。
但是我們為何要使用Node.Js?相比傳統的webserver服務模式,nodejs有什麽優點優勢?
Node.Js是基於javascript語言,建構在google V8 engine以及Linux上的一個非阻塞事件驅動IO框架。nodejs是單進程單線程,但是基於V8的強大驅動力,以及事件驅動模型,nodejs的性能非常高,而且想達到多核或者多進程也不是很難(現在已經有大量的第三方module來實現這個功能)。
這裏主要不是介紹nodejs具體應用代碼,而是想介紹一下事件驅動編程。
在這篇文章(1)裏面,Dan York介紹了兩種典型的事件驅動實例。
第一個例子是關於醫生看病。
在美國去看醫生,需要填寫大量表格,比如保險、個人信息之類,傳統的基於線程的系統(thread-based system),接待員叫到你,你需要在前臺填寫完成這些表格,你站著填單,而接待員坐著看你填單。你讓接待員沒辦法接待下一個客戶,除非完成你的業務。
想讓這個系統能運行的快一些,只有多加幾個接待員,人力成本需要增加不少。
基於事件的系統(event-based system)中,當你到窗口發現需要填寫一些額外的表格而不僅僅是掛個號,接待員把表格和筆給你,告訴你可以找個座位填寫,填完了以後再回去找他。你回去坐著填表,而接待員開始接待下一個客戶。你沒有阻塞接待員的服務
你填完表格,返回隊伍中,等接待員接待完現在的客戶,你把表格遞給他。如果有什麽問題或者需要填寫額外的表格,他給你一份新的,然後重復這個過程。
這個系統已經非常高效了,幾乎大部分醫生都是這麽做的。如果等待的人太多,可以加入額外的接待員進行服務,但是肯定要比基於線程模式的少得多。
第二個例子是快餐店點餐。
在基於線程的方式中(thread-based way)你到了櫃臺前,把你的點餐單給收銀員或者給收銀員直接點餐,然後等在那直到你要的食物準備好給你。收銀員不能接待下一個人,除非你拿到食物離開。想接待更多的客戶,容易!加更多的收銀員!
當然,我們知道快餐店其實不是這樣工作的。他們其實就是基於事件驅動方式,這樣收銀員更高效。只要你把點餐單給收銀員,某個人已經開始準備你的食物,而同時收銀員在進行收款,當你付完錢,你就站在一邊而收銀員已經開始接待下一個客戶。在一些餐館,甚至會給你一個號碼,如果你的食物準備好了,就呼叫你的號碼讓你去櫃臺取。關鍵的一點是,你沒有阻塞
Node.Js做了什麽工作呢?
傳統的web server多為基於線程模型。你啟動Apache或者什麽server,它開始等待接受連接。當收到一個連接,server保持連接連通直到頁面或者什麽事務請求完成。如果他需要花幾微妙時間去讀取磁盤或者訪問數據庫,web server就阻塞了IO操作(這也被稱之為阻塞式IO).想提高這樣的web server的性能就只有啟動更多的server實例。
相反的,Node.Js使用事件驅動模型,當web server接收到請求,就把它關閉然後進行處理,然後去服務下一個web請求。當這個請求完成,它被放回處理隊列,當到達隊列開頭,這個結果被返回給用戶。這個模型非常高效可擴展性非常強,因為webserver一直接受請求而不等待任何讀寫操作。(這也被稱之為非阻塞式IO或者事件驅動IO)
考慮下面這個過程:
1,你用瀏覽器訪問nodejs服務器上的"/about.html"
2,nodejs服務器接收到你的請求,調用一個函數從磁盤上讀取這個文件。
3,這段時間,nodejs webserver在服務後續的web請求。
4,當文件讀取完畢,有一個回調函數被插入到nodejs的服務隊列中。
5,nodejs webserver運行這個函數,實際上就是渲染(render)了about.html頁面返回給你的瀏覽器。
好像就節省了幾微秒時間,但是這很重要!特別是對於需要相應大量用戶的web server。
這也就是為什麽Node.Js這麽熱這麽惹人關註。而且它還使用了一個非常通用的編程語言Javascript,也讓開發者可以快速容易的編寫高可擴展性服務器。
(1) http://code.danyork.com/2011/01/25/node-js-doctors-offices-and-fast-food-restaurants-understanding-event-driven-programming/
nodejs 事件驅動