『與善仁』Appium基礎 — 13、補充:node.js介紹
參考:
提示:上一篇文章中提到了可以使用
node.js
的方式來安裝Appium服務,我之前也每用過node.js
,這裡補充一下對node.js
的基礎認識。
1、node.js是什麼?
node.js
是一個JavaScript
的執行環境和api
集合,為本來只能在瀏覽器沙盒中執行的JavaScript
提供了與作業系統進行互動的能力,從此JavaScript
也和其它的後臺語言一樣可以操作檔案,監聽網路埠,讀寫資料庫,與作業系統底層互動了。
2、為什麼我們要用node.js?
node.js
有非阻塞,事件驅動I/O
等特性,從而讓高併發(high concurrency
)在的輪詢(Polling
)和comet
構建的應用中成為可能。
因為傳統的伺服器是很難設計出能輕鬆併發上萬連線的服務端。node.js
通過提供原生的非同步服務模型,能夠輕鬆實現高併發伺服器,從前需要各種優化才能實現的併發效能,現在node.js
3、node.js為什麼能高併發?
要回答這個問題,首先要問為什麼其它的同步模型的服務端為什麼難以實現高併發?同步模型伺服器在收到一個請求以後,就要建立一個新的執行緒來處理使用者請求,這個執行緒有建立開銷,執行時有記憶體佔用,執行時對於檔案操作和資料庫讀取需要阻塞後續程式碼,處理完請求之後需要再銷燬相應執行緒,即使使用執行緒池來操作,也有執行緒切換開銷,而且多執行緒程式設計對於開發者的心智要求也很高,很容易寫出有問題的程式碼。所以,同步模型的時間開銷和記憶體開銷在併發量上來之後會線性增加,很快就會達到伺服器無法支撐的地步,只有通過特殊優化才能支撐起高併發。
node.js
提供了大量的非同步api
I/O
操作比如網路請求,檔案讀寫,資料庫讀寫等可以非同步執行,I/O
的操作在底層的執行緒池進行,操作完成之後通知主執行緒,再由主執行緒處理網路請求。不用每一個請求來臨時就建立一個新的執行緒,節省了執行緒建立和銷燬的時間開銷,也減少了記憶體的佔用。有可能在低併發量的時候不如同步模型,但是在併發量高的時候,因為不會隨著併發量的提高建立對應數量的執行緒,因此避免了很多建立執行緒的時間和執行緒佔用的記憶體空間,這樣就可以使用有限的伺服器資源提供更高的併發效能了。
解釋說明:
瀏覽器給網站發請求的過程一直沒怎麼變過,當瀏覽器給網站發了請求,伺服器收到了請求,然後開始搜尋被請求的資源。如果有需要,伺服器還會查詢一下資料庫,最後把響應結果傳回瀏覽器。不過,在傳統的Web伺服器中(比如Apache
),每一個請求都會讓伺服器建立一個新的程序來處理這個請求。
後來有了Ajax
技術,我們就不用每次都請求一個完整的新頁面了,取而代之的是,每次只請求需要的部分頁面資訊就可以了。這顯然是一個進步,但是比如你要建一個FriendFeed
這樣的社交網站(類似人人網那樣的刷朋友新鮮事的網站),你的好友會隨時的推送新的狀態,然後你的新鮮事會實時自動重新整理。要達成這個需求,我們需要讓使用者一直與伺服器保持一個有效連線。目前最簡單的實現方法,就是讓使用者和伺服器之間保持長輪詢(long polling
)。
HTTP請求不是持續的連線,你請求一次,伺服器響應一次,然後就完了。長輪詢是一種利用HTTP模擬持續連線的技巧。具體來說,只要頁面載入了,不管你需不需要伺服器給你響應資訊,你都會給伺服器發一個Ajax
請求。這個請求不同於一般的Ajax
請求,伺服器不會直接給你返回資訊,而是它要等著,直到伺服器覺得該給你發信息了,它才會響應。比如,你的好友發了一條新鮮事,伺服器就會把這個新鮮事當做響應發給你的瀏覽器,然後你的瀏覽器就重新整理頁面了。瀏覽器收到響應重新整理完之後,再發送一條新的請求給伺服器,這個請求依然不會立即被響應。於是就開始重複以上步驟。利用這個方法,可以讓瀏覽器始終保持等待響應的狀態。雖然以上過程依然只有非持續的HTTP參與,但是我們模擬出了一個看似持續的連線狀態。
我們再看傳統的伺服器(比如Apache
)。每次一個新使用者連到你的網站上,你的伺服器就得開一個連線。每個連線都需要佔一個程序,這些程序大部分時間都是閒著的(比如等著你好友發新鮮事,等好友發完才給使用者響應資訊。或者等著資料庫返回查詢結果什麼的)。雖然這些程序閒著,但是照樣佔用記憶體。這意味著,如果使用者連線數的增長到一定規模,你伺服器沒準就要耗光記憶體直接癱了。
這種情況怎麼解決?解決方法就是剛才上邊說的:非阻塞和事件驅動。這些概念在我們談的這個情景裡面其實沒那麼難理解。你把非阻塞的伺服器想象成一個loop
迴圈,這個loop
會一直跑下去。一個新請求來了,這個loop
就接收了這個請求,把這個請求傳給其他的程序(比如傳給一個搞資料庫查詢的程序),然後響應一個回撥(callback
)。完事了這loop
就接著跑,接收其他的請求。這樣下來,伺服器就不會像之前那樣傻等著資料庫返回結果了。
如果資料庫把結果返回來了,loop
就把結果傳回使用者的瀏覽器,接著繼續跑。在這種方式下,你的伺服器的程序就不會閒著等著。從而在理論上說,同一時刻的資料庫查詢數量,以及使用者的請求數量就沒有限制了。伺服器只在使用者那邊有事件發生的時候才響應,這就是事件驅動。
FriendFeed
是用基於Python
的非阻塞框架Tornado
(知乎也用了這個框架) 來實現上面說的新鮮事功能的。不過,Node.js
就比前者更妙了。Node.js
的應用是通過JavaScript
開發的,然後直接在Google的變態V8引擎上跑。用了Node.js
,你就不用擔心使用者端的請求會在伺服器裡跑了一段能夠造成阻塞的程式碼了。因為JavaScript
本身就是事件驅動的指令碼語言。你回想一下,在給前端寫JavaScript
的時候,更多時候你都是在搞事件處理和回撥函式。JavaScript
本身就是給事件處理量身定製的語言。
4、Node旨在解決什麼問題?
Node公開宣稱的目標是 “旨在提供一種簡單的構建可伸縮網路程式的方法”。
在 Java 和 PHP 這類語言中,每個連線都會生成一個新執行緒,每個新執行緒可能需要 2 MB 的配套記憶體。在一個擁有 8 GB RAM 的系統上,理論上最大的併發連線數量是 4,000 個使用者。隨著您的客戶群的增長,如果希望您的 Web 應用程式支援更多使用者,那麼,您必須新增更多伺服器。當然,這會增加伺服器成本、流量成本和人工成本等成本。除這些成本上升外,還有一個潛在技術問題,即使用者可能針對每個請求使用不同的伺服器,因此,任何共享資源都必須在所有伺服器之間共享。鑑於上述所有原因,整個 Web 應用程式架構(包括流量、處理器速度和記憶體速度)中的瓶頸是:伺服器能夠處理的併發連線的最大數量。
Node.js
解決這個問題的方法是:更改連線到伺服器的方式。每個連線發射一個在Node.js
引擎的程序中執行的事件,而不是為每個連線生成一個新的 OS 執行緒(併為其分配一些配套記憶體)。Node聲稱它絕不會死鎖,因為它根本不允許使用鎖,它不會直接阻塞I/O
呼叫。Node還宣稱,執行它的伺服器能支援數萬個併發連線。
5、總結:
-
簡單的說
Node.js
就是執行在服務端的JavaScript
技術。
如果你熟悉JavaScript
,那麼你將會很容易的學會Node.js
。 -
Node.js
是一個基於Chrome JavaScript
執行時建立的一個平臺。基於Google的V8引擎,V8引擎執行JavaScript
的速度非常快,效能非常好。
你Chrome瀏覽器中的JavaScript
和Node.js
都在V8引擎上執行。
該引擎將你的JavaScript
程式碼轉換為更快的機器程式碼。
機器程式碼是低階程式碼,計算機可以直接執行而無需先解釋它。 -
Node.js
是一個使用高效、輕量級的事件驅動、非阻塞I/O
模型。 -
Node.js
可以把原來是隻能在瀏覽器中執行的JavaScript
,把它擴充套件成為可以在你的計算機上作為獨立的程式執行。 -
現在你可以用
JavaScript
做更多的事情,而不僅僅是用在網站的互動和特效上。
現在能夠去做幾乎其他後端語言實現的所有功能,(如Python、PHP、Java、Ruby等)。 -
Node.js
的軟體包生態系統npm是全球最大的開源庫生態系統。