前言 近來,幾乎人人都在談論微服務。開發人員都在研究Eric Evan的著作《領域驅動設計》。團隊正在重構一體化應用,尋找限界上下文,並定義通用語言。雖然有不計其數的文章、視訊和座談可以幫助您轉換到微服務,但很少有人願意多花些時間來探討一下某個具體的應用是否應該採用微服務。
使用微服務架構有很多充分的理由,但天下沒有免費的午餐。微服務雖有諸多優勢,但也增加了複雜性。團隊應該積極應對這種複雜性,但前提是應用能夠受益於微服務。
切忌盲目跟風,請負責任地考慮是否採用微服務架構
Matt Stine和我在最近與一家客戶一起研究了他們的一些應用。我們的討論以“一切都應該是微服務”為出發點,因為這在如今已經“司空見慣”。結果談話陷入了僵局,大家就各種實施細節爭論不休。
Matt在白板上寫下了一組原則。這些簡單的句子在這一天剩下的時間裡指導著我們,我們審視應用架構的每個部分,尋找微服務可以交付價值的地方。這個列表徹底改變了對話的氛圍,幫助團隊制定了明智的架構決策。
為了不濫用微服務,我們列出了這組原則,幫助您集中精力開展工作。通過閱讀下面的這些原則,看看特定的應用能否因某一個原則而受益。如果對於以下一個或多個原則,您的回答是“是”,那麼這個功能就適合採用微服務。如果對於每個原則,您的回答都是“否”,那麼您可能會給系統引入偶發複雜性。
01
多個變更速度
系統的各個部分是不是需要以不同的速度或向不同的方向發展?如果是,就分別採用微服務吧。這讓每個元件都有了獨立的生命週期。
在任何系統中都是一些模組很少受影響,而另一些模組似乎每次迭代都會發生變化。我們來舉例說明,假設有一款用於線上零售的一體化電子商務應用。
在日常開發工作中,購物車(Cart)和庫存(Inventory)功能基本上不會受影響。但我們可能會不斷地試驗推薦引擎(Recommendation Engine)。我們還想努力提高搜尋(Search)能力。如果將這兩個模組分別放入微服務中,它們的團隊就能以更快的速度進行迭代,從而讓我們快速交付業務價值。
02
獨立的生命週期
如果一個模組需要有完全獨立的生命週期(是指程式碼提交到生產的流程),那麼它應該採用微服務。它應該有自己的程式碼儲存庫、CI/CD pipeline等。
範圍越小,測試微服務就越容易。我記得以前遇到過一個專案,它的迴歸測試套件需要80個小時!不用說,我們並沒有經常執行完整的迴歸測試(雖然我們真的想這麼做)。微服務方法支援精細的迴歸測試。這為我們節省了大量的時間。我們能夠及早發現問題。
測試不是我們採用微服務的唯一理由。在一些情況下,業務需求可能促使我們採用微服務架構。讓我們以Widget.io一體化應用為例。
企業領導可能發現了新商機,而上市速度至關重要。如果我們決定向一體化應用新增必要的新功能,可能要花很長時間。我們的行動速度無法達到企業的要求。
但作為獨立的微服務,“專案X”(如下所示)可以有自己的部署流水線。這個方法使我們能夠迅速迭代,從新的業務商機中獲利。
03
獨立的可擴充套件性
如果系統各部分的負載或吞吐量特徵不同,它們的擴充套件需求可能也不同。解決方案就是把這些元件放入獨立的微服務中!這樣一來,服務能夠以不同的速度擴充套件。
即使粗略地看一下一般的架構,我們也會發現不同模組具有不同的擴充套件要求。我們從這個角度看一下Widget.io一體化應用。
最有可能的情況是,其中的帳戶管理(Account Administration)功能並不需要承受訂單處理(Order Processing)系統承受的那麼多壓力。過去,我們必須擴充套件整個一體化應用來支援最不穩定元件。這種方法會導致基礎架構成本增加,因為我們不得不在應用的某個部分出現最壞情況時“過度調配”。
如果將訂單處理(Order Processing)功能重構為微服務,我們可以根據需要擴充套件和收縮。結果就如這張圖所示:
04
隔離故障
有時,我們希望將應用與特定型別的故障隔離開來。例如,當我們依賴一項外部服務但這個服務無法滿足我們的可用性目標時,該怎麼辦?我們可以建立微服務,將這種依賴關係與系統的其餘部分隔離。之後,我們可以在該服務中構建合適的故障轉移機制。
在這裡順便給大家推薦一個架構交流群:617434785,裡面會分享一些資深架構師錄製的視訊錄影:有Spring,MyBatis,Netty原始碼分析,高併發、高效能、分散式、微服務架構的原理,JVM效能優化這些成為架構師必備的知識體系。還能領取免費的學習資源。相信對於已經工作和遇到技術瓶頸的碼友,在這個群裡會有你需要的內容。
再來看一看我們的示例Widget.io一體化應用。庫存(Inventory)功能恰好與一個遺留的資料倉儲系統互動,而後者的正常執行時間不夠好。如果將庫存(Inventory)模組重構到微服務中,我們就可以在可用性方面實現服務級別目標。我們可能需要增加帳戶冗餘以應對脆弱的資料倉儲系統。我們還可以引入一些最終一致性機制,比如Redis中的快取清單。但現在,轉型到微服務減輕了由於不可靠的第三方依賴關係而導致的效能不佳。
05
簡化與外部依賴關係的互動
這個原則與“Isolated Failure”類似。換一種說法是:我們更專注於保護系統免受頻繁變化的外部依賴關係的影響。(這也可能是供應商依賴關係,即把一個服務提供商換成另一個,比如更換負責付款處理的供應商)。
微服務相當於一個間接的層,把您與第三方依賴關係隔離。我們可以在核心應用與依賴關係之間部署一個由我們控制的抽象層,而不是直接呼叫依賴關係。此外,我們可以構建這個抽象層,讓應用更便於使用,因為隱藏了依賴關係的複雜性。如果未來發生變更,必須進行遷移,那麼變更將只限於“外觀”,不需要更大規模的重構。
06
根據工作自由選擇合適的技術
利用微服務,團隊可以自由使用自己喜歡的技術堆疊。在某些情況下,一項業務要求恰好適合一項特定的技術選型。而其他時候,技術選型由開發人員的偏好和熟悉程度決定。
注意:這個原則並不是說可以隨意使用任意技術!請向團隊提供關於技術選型的指導。過多的分散堆疊會在認知上增加開銷,比基於“一刀切”模型實現標準化更糟糕。為一個堆疊及時更新第三方儲存庫就已經很有挑戰性了,更何況是將這種費力工作擴大四倍或五倍,會大大增加公司的負擔。請採取有效措施,關注那些您知道如何提供支援的“妥善方法”。
在Widget.io這個例子中,與其餘模組相比,搜尋(Search)功能可能會受益於不同的語言或資料庫選擇。如果需要,這麼做非常簡單。當然,出於其他原因,我們已經對它進行了重構!
文化
上面都是技術討論。那麼在文化上呢?
沒有任何技術決策是憑空想出來的。因此,在深入瞭解精彩的微服務世界之前,先了解一下您的企業。您的組織結構是否能輕鬆支援微服務架構?根據康威定律,您的成功機率如何?
“經過深思熟慮的早期經驗教訓可能會抵消康威定律的效果。”
——- @jmckenty
Mel Conway在50年前總結說,任何企業設計的系統都會反映該企業的組織結構。換句話說,如果團隊的組織結構不是小型自主團隊,那麼工程師不可能創造出由小型自主服務組成的軟體。這種認識促成了反向康威操縱,即鼓勵團隊改變其組織結構,來反映他們渴望在應用中看到的架構。
您還應該考慮文化是否準備就緒。微服務提倡以小批量方式頻繁進行更改,這種頻率一般與傳統的季度釋出週期相沖突。利用微服務,您不會遇到程式碼凍結或“一窩蜂式”的程式碼整合。雖然基於微服務的架構肯定能在傳統的瀑布式環境中執行,但您無法發揮它的全部優勢。
還要考慮如何調配基礎架構。關注自助服務和優化價值流的團隊一般都採用微服務模式。Pivotal Cloud Foundry等平臺幫助團隊在幾分鐘內(而不是幾周或幾個月)快速部署、測試和優化服務。開發人員只需按一下按鈕即可啟動例項,這種做法能夠推動實驗和學習。Buildpack可以自動執行依賴關係管理。這意味著開發人員和運維人員可以專注於交付業務價值。
即使是你所在行業中的公司也可以從每年部署四次轉型到一個月部署上千次。
最後,我們針對應用問兩個具體問題:
這款應用是否有多個業務所有人?如果系統有多個獨立的自主業務所有人,則會有兩種不同變更來源。這種情況可能會導致衝突。利用微服務,您可以實現“獨立的生命週期”,讓不同的支持者滿意。
這款應用是否由多個團隊所有?多個團隊開發一個系統的“協調成本”可能很高。因此請為他們定義API。之後,每個團隊都可以使用Spring Cloud Contract構建獨立的微服務,也可以使用Pact進行消費者驅動的合同
測試。
對於這些問題,如果您有任一項回答是“是”,那麼您就應該使用微服務解決方案。
總結
微服務之路的想法是好的。但有不少團隊在沒有分析需求的情況下就踏上了微服務的浪潮。微服務非常強大,大家都想用!但一定要做出權衡取捨。而且必須要了解應用的業務推動因素,這是無可替代的,因為這對確定合適的架構方法至關重要。