“騎手與大象”架構(gòu):超越微服務(wù)與單體之爭的務(wù)實之道?
在軟件架構(gòu)的江湖里,關(guān)于“微服務(wù)”與“單體”的論戰(zhàn),幾乎從未停歇。一方推崇微服務(wù)的靈活性、可擴展性和獨立部署,另一方則堅守單體的簡潔性、低通信開銷和易于本地調(diào)試。近年來,我們甚至看到像亞馬遜 Prime Video 這樣重量級的玩家,也公開分享了其從微服務(wù)“回歸”到某種形式的單體(或者說更粗粒度的服務(wù))的實踐,引發(fā)了業(yè)界新一輪的思考。
這不禁讓我們反問:微服務(wù)與單體,真的就是非此即彼的“二元對立”嗎?
最近,國外一家名為DealGate公司的一篇文章《Introducing the Rider and Elephant Software Architecture》,提出了一種他們稱之為“騎手與大象”的架構(gòu)模式,試圖在這場看似無解的爭論中,找到一條務(wù)實的中間道路。這種模式不僅在他們的實踐中取得了顯著成效,其背后的設(shè)計哲學(xué)和對技術(shù)選型的思考,也頗具啟發(fā)意義。
“騎手與大象”:一個古老隱喻的現(xiàn)代架構(gòu)演繹
DealGate 將其架構(gòu)模式命名為“騎手與大象”,其靈感來源于心理學(xué)中的一個經(jīng)典比喻:人類的思維由兩部分組成——理性的“騎手”(對應(yīng)我們發(fā)達的前額葉皮層,負責(zé)規(guī)劃、分析和決策)和感性的、更強大的“大象”(對應(yīng)我們原始的、更底層的“蜥蜴腦”或“穴居人腦”,驅(qū)動著本能和情緒)。騎手雖然可以嘗試引導(dǎo)大象,但無法完全控制它;而如果騎手想獨自前行,又會發(fā)現(xiàn)大象的力量是其無法比擬的。只有當(dāng)騎手與大象協(xié)同合作時,才能發(fā)揮出最大的效能。
在 DealGate 的架構(gòu)中,這個隱喻被巧妙地映射到了技術(shù)組件上:
- “大象 (Elephant)”:由 Go語言構(gòu)建的應(yīng)用。它不包含任何復(fù)雜的業(yè)務(wù)邏輯,但卻承擔(dān)著所有“臟活累活”——大規(guī)模的、高并發(fā)的數(shù)據(jù)處理。在 DealGate 的場景中,這可能意味著在任何時刻都有數(shù)萬個 goroutine 在處理圖像、PDF,抓取數(shù)千萬級別的網(wǎng)頁,并在每個網(wǎng)頁上運行數(shù)千萬次的正則表達式匹配。“大象”的核心職責(zé)是:強大、高效、能扛事兒。
- “騎手 (Rider)”:由NextJS (Node.js) 構(gòu)建的應(yīng)用。它承載了所有的業(yè)務(wù)邏輯、數(shù)據(jù)庫訪問、用戶交互等。“騎手”的核心職責(zé)是:靈活、敏捷、快速響應(yīng)業(yè)務(wù)變化。
- 韁繩 (Communication):“騎手”通過 gRPC 來“引導(dǎo)”和控制“大象”,兩者之間保持低開銷、高效率的通信。
這種架構(gòu)的核心思想是:將需要極致性能和高并發(fā)處理的“重計算”部分(大象),與需要快速迭代和靈活業(yè)務(wù)邏輯的“輕應(yīng)用”部分(騎手)進行分離,并讓它們通過高效的通信方式協(xié)同工作。
為何選擇“騎手與大象”?DealGate 的實踐與思考
DealGate 之所以采用這種架構(gòu),源于他們在實際業(yè)務(wù)中遇到的挑戰(zhàn)和對現(xiàn)有架構(gòu)模式的反思。
- 對“微服務(wù) vs 單體”的“虛假二分法”說不:他們認為,單純地在微服務(wù)和單體之間做選擇,往往忽略了業(yè)務(wù)的復(fù)雜性和多樣性。他們希望能夠“have the best of both worlds”(取兩者之長)。
- Node.js/NextJS 的局限性:盡管 DealGate 的主要應(yīng)用是用 NextJS 編寫的,但他們發(fā)現(xiàn),即使 Node.js 在 I/O 和網(wǎng)絡(luò)處理上有多線程優(yōu)勢,其正則表達式等 CPU 密集型操作仍然受限于單線程(JavaScript 的執(zhí)行模型)。當(dāng)需要在后臺進行大量正則匹配,同時還要響應(yīng) Web 應(yīng)用請求時,性能瓶頸就顯而易見了。
- Go 語言的“大象”潛質(zhì):文章中明確指出:“Go語言非常適合這種場景,你可以輕松地扔給它數(shù)萬個CPU密集型進程,它會愉快地處理掉所有這些”。這充分肯定了 Go 語言在并發(fā)處理和性能方面的核心優(yōu)勢。
- 對微服務(wù)通信開銷的警惕:DealGate 批評了許多微服務(wù)架構(gòu)使用 JSON 進行進程間通信的做法,認為其“序列化和反序列化開銷是令人發(fā)指的”。他們選擇 gRPC,正是為了最大限度地降低“騎手”與“大象”之間的通信成本,確保即使在需要傳輸大量數(shù)據(jù)(因為“大象”不包含業(yè)務(wù)邏輯,需要被視為“愚笨的工人”)的情況下,也能保持高效。
Go 語言:扮演“大象”的理想之選
在“騎手與大象”的架構(gòu)中,Go 語言之所以被選中扮演“吃苦耐勞的大象”,并非偶然。這得益于 Go 語言的核心特性:
- 極致的并發(fā)性能:Goroutine 和 Channel 機制,配合高效的調(diào)度器,使得 Go 能夠輕松創(chuàng)建和管理海量的并發(fā)任務(wù),這對于處理 DealGate 所述的“數(shù)萬個 goroutine 同時處理數(shù)據(jù)”的場景至關(guān)重要。
- 高效的執(zhí)行效率:Go 語言編譯為原生機器碼,其性能接近 C/C++,遠超解釋型語言,非常適合 CPU 密集型的數(shù)據(jù)處理任務(wù)。
- 強大的標(biāo)準(zhǔn)庫:Go 的標(biāo)準(zhǔn)庫提供了豐富的網(wǎng)絡(luò)編程、文本處理(包括正則表達式)、數(shù)據(jù)編解碼等功能,為構(gòu)建“大象”應(yīng)用提供了堅實的基礎(chǔ)。
- 簡潔的部署:Go 應(yīng)用可以編譯成單個靜態(tài)鏈接的可執(zhí)行文件,部署簡單,依賴少。
可以說,Go 語言的設(shè)計哲學(xué)和核心能力,使其成為承載這種“無業(yè)務(wù)邏輯、高并發(fā)、重計算”角色的理想選擇。
語言選型的“二八原則”與“務(wù)實主義”
“騎手與大象”架構(gòu)的另一個核心啟示,在于其對不同技術(shù)棧的選擇策略,體現(xiàn)了一種深刻的“務(wù)實主義”和對“成本效益”的考量。
文章明確反駁了“既然有更高性能的語言(如 Rust 或 Go 本身),為什么不把所有應(yīng)用都用它來寫?”的觀點,并將其類比為“那所有應(yīng)用都應(yīng)該用匯編來寫了”。
其核心邏輯是:
- 高級語言(如 JavaScript, Python)的優(yōu)勢:更安全(內(nèi)存管理等)、生產(chǎn)力更高(表達力強、語法糖和輪子多)、開發(fā)者社群更大、單位時間開發(fā)成本相對更低。
- 高性能/底層語言(如 Go, Rust, C++)的優(yōu)勢:性能極致、對系統(tǒng)資源有更精細的控制。但通常也意味著更陡峭的學(xué)習(xí)曲線、更高的開發(fā)成本、以及(在某些情況下)更長的開發(fā)周期。
DealGate 的策略是:“在你必須快的地方快,其他一切都選擇高級語言和(相對)單體的模式。” 這意味著:
- 將昂貴的、需要精細優(yōu)化的高性能代碼(大象)限制在最小的必要范圍內(nèi)(例如,只占整個業(yè)務(wù)系統(tǒng)的 10%)。
- 將大部分的業(yè)務(wù)邏輯、用戶交互(騎手)用生產(chǎn)力更高、開發(fā)更快的高級語言來實現(xiàn)。
這種“混合編程”或“多語言架構(gòu)”的思路,實際上是在性能、開發(fā)效率、人才獲取成本、維護成本等多個維度之間進行權(quán)衡和優(yōu)化。它提醒我們,技術(shù)選型不應(yīng)盲目追求“最新最酷”或“性能極致”,而應(yīng)服務(wù)于業(yè)務(wù)需求,并充分考慮團隊和公司的實際情況。
文章中也提及了對“Just write Rust”(就用 Rust 寫)這類口號的反思,指出大多數(shù)公司和開發(fā)者可能無法承擔(dān)全員學(xué)習(xí)和使用像 Rust 這樣“高門檻”語言的成本。這并非否定 Rust 的優(yōu)秀,而是強調(diào)技術(shù)選型的現(xiàn)實約束。
小結(jié):“沒有完美的解決方案,只有明智的權(quán)衡”
“沒有完美的解決方案,只有權(quán)衡取舍”。DealGate 的文章以這句經(jīng)典的名言作為總結(jié),恰如其分。
“騎手與大象”架構(gòu),正是在微服務(wù)的靈活性、分布式能力與單體的低心智負擔(dān)、高開發(fā)效率之間做出的一種明智權(quán)衡。它并非適用于所有場景的“銀彈”,但在類似 DealGate 這樣需要處理大規(guī)模數(shù)據(jù)密集型任務(wù),同時又需要快速迭代業(yè)務(wù)邏輯的場景下,無疑提供了一種極具價值的、務(wù)實的架構(gòu)思路。
它也再次印證了一個樸素的道理:優(yōu)秀的架構(gòu)設(shè)計,往往不是對某種“主義”的盲從,而是對業(yè)務(wù)需求的深刻理解和對不同技術(shù)優(yōu)劣的精準(zhǔn)把握,最終在各種約束條件下找到那個“恰到好處”的平衡點。
或許,在微服務(wù)與單體的喧囂爭論之外,我們更應(yīng)該學(xué)習(xí)這種“騎手與大象”的智慧——在正確的地方,用正確的方式,做正確的事情。
參考文獻: Introducing the Rider and Elephant Software Architecture - https://d-gate.io/blog/rider-and-elephant-architecture