天天看點

微服務架構系列主題:從單體遷移至微服務,需要有足夠的理由

文本轉自:InfoQ 架構頭條

微服務是一種非常流行的 Web 軟體架構,有着大量知名的實踐者和支援者。

Facebook、Uber、Groupon、Klarna、Amazon、Netflix、eBay、Comcast 等公司都采用了微服務架構。

你的公司可能與這些公司不同,也就是說,你的團隊可能和這些公司的團隊一點都不像,你可能不會面臨和他們一樣的問題。

如果你就在這些公司當中,那麼請停止閱讀本文,因為你确實可能需要微服務。

1 微服務“稻草人”

微服務提供了許多所謂的好處。但問題的本質不在于微服務是否提供了這些好處,而在于有些問題并非隻有微服務能夠解決。

在某種程度上,這些問題中的大部分(如果不是全部的話)都可以通過單體服務來解決。

當有人例舉微服務架構的優點時,其潛台詞就是——為了解決這些問題,必須采用微服務架構。

事實上,微服務架構就是要你通過增加額外的層和一定程度的靈活性來解決這些問題。

這裡的關鍵是增加額外的東西。

微服務不是免費的,它的建構和維護成本是出了名的高。

如果你确實需要額外的靈活性,那麼從整體上看,付出額外的成本可能可以獲得相應的回報。這個時候,也許微服務架構是正确的選擇,也許你可以認真考慮一下。

但如果你不需要額外的靈活性呢?那麼你的技術棧就是過度設計了,這将嚴重阻礙你的團隊向客戶傳遞價值的能力。

接下來,我們将列出微服務最經常被提及的好處,并看看如何用單體服務來達到同樣的目的。

2 伸縮性

在微服務架構中,應用程式的每一個功能都運作在自己的資源上,并且這些資源可以獨立伸縮。這将為你提供高度的控制能力,你可以精确地控制配置設定給每個功能的資源的數量和類型。

但你真的需要這種程度的控制能力嗎?

應用程式的不同功能是否需要處理不同級别的負載?

它們會以不同的速度增長嗎?

它們在 CPU、記憶體、存儲和 GPU 方面有不同的要求嗎?

更新伺服器

對于許多團隊來說,通過簡單地增加伺服器數量或更新伺服器配置就可以解決資源差異問題,這樣做的成本更低。也就是說,在大多數情況下,不優化基礎設施更符合成本效益。

優化單體服務

解決單體服務的性能問題和瓶頸比遷移到新的架構更容易。這與具體的技術棧有關,但應該不需要太大的工作量。

将流量路由到獨立可伸縮的叢集

如果你有多台伺服器,可以在這些伺服器前面運作某種負載均衡器。你可以利用這個負載均衡器将流量路由到獨立可伸縮的叢集中。

你還可以使用獨立可伸縮的隊列将異步任務放在背景執行。不過你需要確定有足夠多的隊列來實作控制粒度,保持基礎設施成本位于合理的水準。

3 故障隔離

應用程式的單個故障不影響其他特性,這是設計合理的微服務架構能夠為我們帶來的一個好處。

将流量路由到隔離叢集

将不同類型的流量路由到不同的叢集,這樣有助于避開某些故障。

總結一下大多數曆史錯誤來自哪裡,這樣你就知道該如何更好地路由流量。如果你想解決“吵鬧的鄰居”問題,可能需要基于帳戶 ID 進行路由。如果你有一個脆弱但不那麼重要的功能,很容易拖垮服務,那麼可以把它的流量路由到它自己的應用執行個體叢集中。如果你有經常出問題的背景作業,請将它們放入自己的隊列中,避免影響了其他作業。

自動化測試

預防勝于治療。如果你能夠防止或減少故障數量,那就不需要過多地擔心如何隔離它們。

關鍵在于要培養一種健康的測試文化,確定對傳遞的産品的品質有足夠的信心。這種信心不僅是指能夠可靠地傳遞所需的功能,而且需要能夠應對生産負載的壓力。

4 自由選擇程式設計語言和技術

在為服務引入新的程式設計語言和技術時,如果服務不是獨立的,就沒有太多選擇。

在大多數情況下,這更像是一個特性而不是一個 Bug。在選擇程式設計語言和技術時,給工程師太多的選擇可能會導緻技術棧過于分散和複雜。

我們應該擁抱單體服務的簡單性和一緻性。

如果你确實對特定程式設計語言有特定的需求,可以考慮使用單獨的服務,但你需要權衡額外的技術所帶來的好處和它的維護成本。

5 資料安全

你覺得保護單體服務很難嗎?在微服務架構中,這項工作會更加複雜。技術棧複雜性的增加隻會增加攻擊表面積。

保護單體服務

确實,将功能隔離到不同的服務中有助于對每個服務應用不同級别的安全性。但是,我們還需要考慮一下這種級别的控制是否是必需的。

将整個單體服務的安全性設定為最進階别是否更容易些?

你的資料是否有不同的安全性需求?

6 團隊自治

我非常喜歡自治的跨職能團隊,但令我感到困惑的是為什麼要通過引入邊界來實作團隊自治。

讓每個團隊擁有特定的獨立系統似乎是一種提高團隊自治的方法,但實際上,它可能會适得其反。

假設我的團隊需要修改由另一個團隊維護的功能。在微服務架構中,我需要先了解這個服務才能對其做出修改,甚至可能需要等待這個服務所屬的團隊來做出變更。如果這個功能是在單體系統中,那麼我很有可能已經很熟悉它的代碼,或至少熟悉它的約定。

團隊自治的程度取決于子產品化的好壞和系統的一緻性,無論是單體還是微服務都無法在這兩方面同時保證或破壞團隊自治。微服務要求系統的子產品化,而單體傾向于鼓勵更多的一緻性。

對單體進行子產品化

從本質上講,微服務架構将迫使你對系統進行子產品化。在這裡,單體并不能提供太多幫助(盡管你所選擇的單體架構可能會有所幫助),但它們也不會妨礙你實作子產品化。

我們可以考慮使用具有有限關注點的松散耦合的子產品化代碼,無論你是否碰巧在這些關注點之間增加了邊界複雜性。

微服務并不能保證良好的子產品化

雖然微服務強制進行子產品化,但并不能保證良好的子產品化。如果沒有經過充分的設計,微服務很容易成為緊密耦合的“分布式單體”。

如果你無法成功地将一個單體子產品化,也就無法建構出一個成功的微服務架構。

微服務強制進行子產品化,但要實作良好的子產品化是很困難的。

7 獨立部署

在進行獨立部署時,你需要做很多變更,這些會成為你的日常工作,并且會成為瓶頸。

協調大量的服務部署将使快速釋出變得更加困難和複雜。

分解複雜的變更

在單體系統中,我們也可以将複雜、有風險的變更分解為單獨的部署。一個常見的例子是使用單獨的 PR 和部署進行向前或向後相容的遷移。

這顯然增加了與微服務類似的釋出複雜性。你可能不會輕率地使用它,但它确實提供了微服務的一些好處,是以你不必在每次發生變更時都使用它。

8 依賴管理

在微服務架構中,你可以為每一個服務使用獨立的依賴項,但你真的需要這麼做嗎?

在一個大型的單體系統中管理依賴項已經足夠困難了,雖然将它分解成幾個較小的服務可以簡化單個服務的管理,但從整體上看卻進一步複雜化了。

對于單體系統,你遲早會陷入“依賴地獄”,并出現依賴沖突。微服務并不能確定可以完全避免這種情況,但應該可以減少出現問題的可能性。

保持依賴項最新

保持依賴項最新顯然是可取的,但在現實當中,通常允許漏掉一些東西。

保持依賴項最新可用版本可能會加劇這個問題,因為一個依賴項可能比其他相關依賴項釋出得更快。但不管怎樣,“保持最新”并不意味着在任何情況下都要更新到最新版本。

9 代碼更簡單、更容易了解

這個好處往好了說是有點虛僞的,往壞了說就是赤裸裸的謊言。

當然,每一個微服務都更簡單,更容易了解,但整個系統會更加複雜,更難了解。你并沒有消除複雜性,反而增加了複雜性,隻是把它轉移到了其他地方。

對單體進行子產品化

我們沒有必要為了讓工程師更容易了解代碼而引入邊界和隔離。

将單體分解成具有明确定義和有限關注點的子產品與将一個系統分解成單獨的服務相比,了解起來同樣容易(如果不是更容易的話)。

10 但我們感受到了單體的痛點

如果你正在遭遇單體的痛點,那可能是因為你的單體存在設計問題,而不是因為它是一個單體。

你可能已經努力通過使用工具和進行子產品化來改進單體的代碼品質,如果還在經曆痛點,那麼可能是時候考慮微服務了。但如果你還沒這麼做,可能隻需要嘗試改進你的單體。

開發軟體并非易事,開發一個包含了大量随時間變化的活動部件的大型系統更是難上加難。

我不想評判任何人,但如果你認為你所面臨的問題都可以通過微服務來解決,甚至簡化,那麼你将陷入痛苦的深淵。

11 我需要微服務嗎

單體和微服務是兩種互相排斥的思維模式。新舊之别,對錯之别,二選一。

事實是,它們都是有效的方法,但需要做出不同的權衡。選擇哪一個取決于具體的情況,而且需要經過深度的思考。

這個選擇本身并不是簡單的二選一,在某些情況下,需要在逐個特性的基礎上做出選擇,而不是簡單地針對整個組織的工程團隊做出選擇。

12 你應該考慮微服務嗎?

這要視情況而定。你可能可以從微服務架構中受益。

在某些情況下,微服務确實可以為我們帶來好處,但如果你是一個中小型的團隊或處于項目的早期,那麼你可能不需要微服務。

13 不相信?請問問周圍的人

如果你看一下整個行業,你會發現無數關于微服務的警示故事,以及它們給團隊帶來的問題。

Segment 就是一個非常典型的逃離微服務架構的例子。

這同樣适用于單體與微服務的選擇,在執行過程中出了問題并不意味着它們存在根本性的缺陷。

如果你打算采用微服務架構,你需要睜大眼睛,接受折衷方案,并為取得成功準備好所需的資源。

14 我的觀點

對于中小型的工程團隊來說,單體應該仍然是預設的選擇。微服務也是一種選擇,但你需要有足夠的理由來證明采用它是合理的。

對于中大型團隊,可以考慮使用微服務,但要注意做出合理的權衡。

繼續閱讀