第一個例子是關於醫生看病。html
在美國去看醫生,須要填寫大量表格,好比保險、我的信息之類,傳統的基於線程的系統(thread-based system),接待員叫到你,你須要在前臺填寫完成這些表格,你站着填單,而接待員坐着看你填單。你讓接待員沒辦法接待下一個客戶,除非完成你的業務。node
想讓這個系統能運行的快一些,只有多加幾個接待員,人力成本須要增長很多。web
基於事件的系統(event-based system)中,當你到窗口發現須要填寫一些額外的表格而不單單是掛個號,接待員把表格和筆給你,告訴你能夠找個座位填寫,填完了之後再回去找他。你回去坐着填表,而接待員開始接待下一個客戶。你沒有阻塞接待員的服務。數據庫
你填完表格,返回隊伍中,等接待員接待完如今的客戶,你把表格遞給他。若是有什麼問題或者須要填寫額外的表格,他給你一份新的,而後重複這個過程。編程
這個系統已經很是高效了,幾乎大部分醫生都是這麼作的。若是等待的人太多,能夠加入額外的接待員進行服務,可是確定要比基於線程模式的少得多。瀏覽器
第二個例子是快餐店點餐。服務器
在基於線程的方式中(thread-based way)你到了櫃檯前,把你的點餐單給收銀員或者給收銀員直接點餐,而後等在那直到你要的食物準備好給你。收銀員不能接待下一我的,除非你拿到食物離開。想接待更多的客戶,容易!加更多的收銀員!函數
固然,咱們知道快餐店其實不是這樣工做的。他們其實就是基於事件驅動方式,這樣收銀員更高效。只要你把點餐單給收銀員,某我的已經開始準備你的食物,而同時收銀員在進行收款,當你付完錢,你就站在一邊而收銀員已經開始接待下一個客戶。在一些餐館,甚至會給你一個號碼,若是你的食物準備好了,就呼叫你的號碼讓你去櫃檯取。關鍵的一點是,你沒有阻塞下一個客戶的訂餐請求。你訂餐的食物作好的事件會致使某我的作某個動做(某個服務員喊你的訂單號碼,你聽到你的號碼被喊到去取食物),在編程領域,咱們稱這個爲回調(callback function)。性能
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。
Dan York原文:Node.js, Doctor’s Offices and Fast Food Restaurants – Understanding Event-driven Programming