Node.js適合做主流大型系統嗎?

banq發表於2013-12-24


這是來自richardrodger一篇博文,主要闡述微服務和模式匹配(訊息),透過Node.js建立一個Http伺服器作為微服務,微服務之間透過訊息傳遞,以微服務構建模組,進而模組化構建一個大型系統。原文大意如下:

Node.js能做大型系統嗎?回答是肯定的,沃爾瑪(Walmart)和Paypal的案例已經證明,那麼大型的Node.JS適合主流的開發者嗎?如果你認為Node.js這樣的大型系統類似Java和.Net,那麼你肯定認為不行:javascript在支援複雜系統擴充套件性方面是一個弱性的語言。它不是強型別語言,而且有一半的語言是無法使用的。

儘管如此,我們已經建立一些大型的NodeJS系統,下面是我們的總結:

傳統的主流的最大型的系統是龐大的鐵板一塊的monolithic,一個特別大的程式碼庫,有很多檔案,幾千個類無數個配置檔案。如果在javascript中建立這樣的體制,可能會發瘋。那些將Node.js看成類似蜘蛛俠的人只會推崇使用Java和.NET建立龐大的系統。

鐵板一塊式monolithic系統是壞的
什麼是鐵板一塊monolithic系統,最簡單定義就是,你如果拿出來一部分,整體就會執行失敗,每個部分連線到其他部門,相互依存。這個詞也用來指一塊整石頭。

這個詞語來自古希臘,建築直接在洛磯山的懸崖上鑿成,由於直接雕刻整個山,他們是無法修復的,城市最終陷入下降。軟體系統的複雜性隨著時間推移,難以修復和延伸,成本不斷提高。

鐵板一塊式的軟體產生的開發流程和方法危害更大,因為系統有這麼多依賴,你必須關注如何讓開發者在改變它們時非常小心,大量精力用於防止程式碼失敗。從瀑布到敏捷,都是為了鐵板一塊式的軟體服務,都是為了讓軟體變得越來越大。

模組化系統是好的
作為軟體開發者,應該努力避免建立鐵板式系統,那就是建立模組化系統,當一個部分丟失時,整個系統還是可以執行。雖然像集裝箱那樣建立軟體的模組化是一個很艱難的過程,但是我們知道這是處理複雜性的唯一方法。

物件是地獄
為實現模組化系統,物件導向正規化受到推崇,其實物件比你想象中的要相差很多,他們來自天真的數學觀點,是一種純柏拉圖的東西,以相同的屬性和特徵劃分物件,表面上看合理,實際你在打破了現實世界的真實面貌,現實世界是混亂,甚至都打破了數學世界。請問集合是包含自身還是不包含自身呢(banq注:羅素的邏輯悖論)。

物件的最終弱點是,他們只是促成了向鐵板式龐大系統發展,物件只是一個系統需要的袋袋,什麼都可以往裡面裝,你有屬性,私有和公有,你有方法,也許覆蓋了其父類,你也可以有狀態。
有太多的東西可以裝入物件,結果一個巨大的類包含了最糾結最痛苦的大量邏輯。

NodeJs的模式是簡單的
有一個例子認為計算斐波納契數是CPU密集型,而Node.js只有一個執行緒,那麼計算斐波納契數的效能是可怕的。你可以使用非同步委派到到作業系統,使用processes 過程而不是執行緒處理,為了避免CPU密集型的計算,你需要將計算任務放入佇列,然後非同步處理它們。

執行緒是出了名的難,Node.js的勝利就是避免了它們,你的程式碼變得易懂。

有一個問題是在javascript中如何實現單例,實際上在現實中很少會碰到這種問題,因為模組已經幫你照看一切,最好的方式是你使用Node.js建立一個Server,透過網路和其他部分通訊。

NodeJS確實需要你學習一些新模式,主要是回撥模式,回撥函式的簽名有一個規律:如果有錯誤發生,第一個物件是錯誤物件,否則,第一個引數是空的,第二個總是返回的結果。

回撥函式自然地來自Node.js的事件處理迴圈, JavaScript最初用來處理瀏覽器中使用者介面事件,現在非常適合處理伺服器端事件果。

當你開始使用Node.js的第一件事就是建立回撥(像義大利麵條)。你結束了大量的縮排程式碼,使用回撥內嵌回撥。經過一些練習,你很快學會使用命名良好的函式結構化你的程式碼,包括非同步模組庫。

Node.js的另一個重大的模式是流,已經被編寫成API,讓你輕鬆 簡潔操作和轉換資料,你使用管道將資料從一個流接至另外一個惡瘤,你可以讀寫全雙工的資料流。

以正確的方式思考
程式語言會應當讓我在一個正確的層次去思考,可惜大多數語言在此慘遭失敗。程式語言在我們思考複雜性過程中成為我們的羈絆,最終發生抽象洩漏(http://www.jdon.com/46006)。

我們應該改變到以面向行動為導向的看待世界方式,這樣才能建立好一大型系統,為什麼設計模式會失敗?因為他們使用靜態的概念表達世界,而世界並不是這樣,我們的大腦也不是這樣工作的。

比如我們開始一個系統總是從用例開始,這是和靜止的實體無關的,如果是初學者肯定首先編寫一段程式導向的程式碼,然後才建立一些資料結構,我們現在可以遵循這種大腦自然思考方式上做得更好。

什麼是新的設計模式?在我們為客戶開發的專案中,我們使用了兩個主要方式:微服務和模式匹配。

(banq注:之前已經節省了不少翻譯,到這裡才進入主題)

微服務Micro-Services
我們可以用生物細胞作為靈感構建健壯的可擴充套件的系統。生物細胞具有許多有趣的性質。它們體積小,單一用途。

我們不是建立一個鐵板式的100 000行的程式碼庫,建設100個小型服務,每個服務有100行程式碼。弗雷德·喬治(程式設計師無政府狀態的發明者)是這種方法的最大支持者之一,稱這些小程式為微服務。

每個微服務執行一個非常有限的任務。這有很好的效果,他們很容易驗證。您一眼就能看到他們,測試與否都不重要的。在人的方面,這也意味著這種程式碼很容易改寫,甚至使用不同的語言也是這樣。如果一個初級工程師寫不好微服務實現,你可以把它扔掉,並重寫。微服務易於更換。微服務之間透過傳送訊息相互通訊。您可以直接透過內部HTTP傳送這些訊息,或者使用訊息佇列應對大規模。

微服務易於擴充套件和伸縮,能夠達到更精細的粒度級別。目前我們還沒有發現所有這些過程的管理過於繁重。

一般來說,你可以使用監控工具來確保服務保持正常執行。一個服務死了處理就變得相對簡單。你會有一個重要的服務執行多個例項,然後很快重新啟動。如果一些奇怪的事情發生了,也還是重新啟動。事實上,這可以讓你的系統變得非常強大,可以防止各種腐敗現象的積聚。

微服務讓你部署任何系統都很容易。剛開始更換一些服務,看看會發生什麼。回滾是微不足道的 - 重新啟動迴歸舊版本。微服務也讓您的開發團隊可伸縮,無論是在個人和團隊。個人的大腦更容易和微服務一起工作,因為考慮的範圍是如此之小,並且很少有副作用。您可以專心於當前的用例。如果擴充套件到團隊也是很容易,納入新的服務,知曉會有團隊成員之間的一些依賴和堵塞。

最後,微服務以軟體的獨立單元讓你對映到你的用例。他們讓你考慮發生了什麼。這超越了物件概念的範圍。

模式匹配

模式匹配可以讓我們在一個合適水平思考,模式匹配以訊息為核心,服務之間的訊息需要發現一個路徑以便到達正確的目標服務,模式匹配越簡單越好。當然訊息可能並不包括所有的屬性,這是使用切面關注比較方便,比如記錄所有有關儲存資料的訊息,只是在這些訊息出現時抓取,作為日誌專案加入,然後繼續傳送這個訊息,你可以加入許可權 快取等等機制(AOP),所有這些不會影響服務。

一個案例是使用者註冊,你可能有一個基本註冊服務,用來儲存使用者資料到資料庫,但是你要傳送一個歡迎Email,或者做其他一些邏輯,你並不能繼承這個基本類,你只要繼承使用者註冊的訊息即可。

微服務和模式匹配能夠很容易使用Node.js實現,這個工具包是Seneca(http://senecajs.org/)

相關文章