不要從單體開始

…當你的目標是微服務架構時

Photo of Stefan Tilkov

Stefan Tilkov 是 innoQ 的共同創辦人兼首席顧問,這是一家在德國和瑞士設有辦事處的技術諮詢公司。他參與大型分散式系統的設計已超過二十年,使用各種技術和工具,從 C++ 和 CORBA 到 J2EE/Java EE 和 Web 服務,再到 REST 和 Ruby on Rails。他撰寫了許多文章和一本書(「REST und HTTP」,德文),並經常在世界各地的會議上發表演講。

2015 年 6 月 9 日

在過去幾個月,我反覆聽說,獲得成功的微服務架構的唯一方法是先從單體開始。用 Simon Brown 的話來說:如果你無法建構一個結構良好的單體,你憑什麼認為你可以建構一組結構良好的微服務?最近一次——而且一如往常地非常令人信服——對此論點的詮釋來自 Martin Fowler,就在這個網站上。由於我有機會評論較早的草稿,所以我有一些時間思考這件事。我確實思考了,特別是因為我通常發現自己同意他的觀點,而且一些我通常認同其觀點的人似乎也同意他的觀點。

我堅信,從單體開始通常完全是錯誤的做法。

開始建構新系統正是你應該思考將其分割成各個部分的時候。我強烈不同意你可以延後這樣做的想法,正如 Sam Newman 所表達的,他也是我 95% 時間都認同的人

我仍然確信,分割現有的「brownfield」系統比從頭開始分割新的「greenfield」系統容易得多。你擁有更多可以利用的資源。你可以檢查程式碼,可以與使用和維護系統的人員交談。你還知道「好」的樣子是什麼 - 你有一個可以變更的工作系統,讓你更容易知道何時出錯或在決策過程中過於激進。

-- Sam Newman

在大部分情況下,要以這種方式分割現有的巨石系統將非常困難,甚至根本不可能。(這並不表示總是做不到,但這是未來文章的主題。)我同意在嘗試分割系統之前,你應該非常了解你正在建構的網域:在我看來,理想的情況是你正在建構現有系統的第二個版本

如果你真的能夠建構一個結構良好的巨石,你可能根本不需要微服務。這沒問題!我絕對同意 Martin:如果你沒有非常好的理由,你不應該在系統中引入額外的分發複雜性。

(那麼什麼會是一個好理由?有很多,但對我來說,最重要的理由是允許在較大的系統中快速、獨立地傳遞個別部分。在我看來,微服務的主要好處是透過在系統的不同部分之間建立難以跨越的界線,來啟用平行開發。透過這樣做,你會讓做錯事變得困難 - 或至少更困難:也就是連接不應該連接的部分,以及過度緊密地結合需要連接的部分。理論上,如果你只是有紀律地遵循明確的規則,並在巨石應用程式中建立明確的界線,你就不需要微服務;但實際上,我發現只有極少數情況是如此。)

你可能會假設你的巨石中隱藏著許多分隔良好的微服務,只需要提取出來即可。然而,實際上,要避免建立許多預期和非預期的連接非常困難。事實上,微服務方法的重點是讓建立類似這樣的東西變得困難。

但是如果你從一個巨石開始,這些部分將會變得極度緊密地連結在一起。這就是巨石的定義。這些部分將依賴於它們所使用的平台的功能。它們將基於抽象化進行溝通,因為它們都使用相同的函式庫。它們將使用僅在它們在同一個程序中時才可用的方式進行溝通。而這些僅是技術層面的問題!更糟的是,這些部分將(幾乎)自由地共用網域物件,依賴於相同的共用持久性模型,假設資料庫交易容易取得,因此不需要補償… 即使是重構事物和移動它們很簡單的事實,都在你的 IDE 視圖中,一個專案的便利性中,這使得再次切開事物變得極度困難。將現有的巨石拆分成不同的部分是極度困難的。

我堅信,從我們最近的許多專案中獲得的經驗證實了這一點,當你開始時,你應該考慮你建立的子系統,並盡可能獨立地建立它們。當然,你應該只在你相信你的系統足夠大到需要這樣做時才這麼做。如果只有你和你的同事在幾個星期內建立了一些東西,很有可能你不需要這麼做。

但是從一種將你的系統切分成較小部分的方法開始,並將它們每一個都視為一個明確分開的個別系統,有自己的開發、部署和交付週期,以及(可能性)自己的內部架構,是一個非常強大的概念,可以幫助你首先交付一個系統。

那麼有沒有任何實際經驗可以支持這一點?是的,最近我們參與了一些系統,展示了這個概念可以運作,前提是你容忍我所談論的內容比你典型的微服務更大。最顯著的一個是 Otto.de,我與他們的技術負責人一起做了一場演講(你可以在他們其中一位首席架構師撰寫的這篇精采文章中讀到)。但還有很多其他文章,我仍然確信,使用這種方法開始建立一個系統是一個好主意,因為你非常、非常了解你正在建立的網域。

但我認為,從這個討論中可以學到另一個教訓,而且是一個更通用的教訓:小心過於簡單和明顯的架構秘方。這個秘方(從將你的網域切分成不同的獨立部分開始)也不例外。有時候巨石較好的選擇,有時候則不是。如果你決定使用微服務方法建立事物,你需要知道,雖然在每個個別部分中做出局部決策會容易得多,但要改變實現此目的的界線會困難得多。小規模重構變得更容易,大規模重構變得困難得多。

與架構討論總是如此,在每一個個別案例中,你都需要自己做出決策,這是無法迴避的事實。


致謝

對於 Martin Fowler 對本文早期版本提供的評論,以及在過去幾週內持續討論這個主題,我深表感謝。當然,我也非常高興他允許我在這個網站上發布這篇文章。我的同事 Daniel Lübke、Oliver Wolf、Alex Heusingfeld、Till Schulte-Coerne、Andreas Krüger 和 Eberhard Wolff 也提供了寶貴的回饋。特別感謝 Roman Stranghöner 繪製了圖表。

延伸閱讀