微服務踩坑十大教訓 - Dave
當您公司的整體Web應用變得太大而脆弱時,部署變得緩慢而令人恐懼。因此,作為一家軟件公司,您已決定遵循許多其他公司所采用的方法——將這個整體/單體架構拆分為微服務架構。
這個遷移旅程可能漫長而艱難,潛伏著許多錯誤的踩坑,以及您想要避免的路徑。我自己經歷過,也許我的經驗可以提供幫助。
1. 你不知道你為什么采用微服務
對于所有涉及的工作,微服務提供了許多好處。畢竟,這就是貴公司采用它們的原因。
所以告訴我...什么是那些好處?為什么貴公司要轉向微服務?
如果你不知道它們是什么,你就不會看到它們的好處!
盡管您可以通過微服務獲得所有收益,但您將面臨增加的成本、復雜性和痛苦。不幸的是,當您開始部署微服務時,收益不會神奇地實現。取而代之的是,您需要將注意力集中在您試圖解決的挑戰上,并確保您不斷朝著解決這些挑戰的方向前進。這不僅意味著提前規劃,還意味著在此過程中進行路線修正。
此外,這意味著做出一些根本性的改變——技術和組織方面的改變。微服務的許多最大好處不在于微服務本身,而在于它們釋放的非技術優勢。
換句話說,如果您一開始不知道為什么要構建微服務,那么您將遭受所有的痛苦而一無所獲。
它實際上可能不值得!
在決定采用微服務之前,您需要檢查權衡。看看您現在作為一個組織所處的位置。盤點您當前面臨的挑戰,并具體確定您期望微服務如何提供幫助。一旦您清楚地了解您希望獲得的好處,您就可以權衡它們與構建和維護微服務的缺點。只有這樣,你才能認為這是值得的。
(banq注:這種觀點可能隱含大量調查思考和預設,其實只有進入遷移過程這個上下文,你才可能在實施過程中敏捷調整你的預設目標,否則在實施之外觀看預設都是看上去很美的花朵,過度設計,過度評估,不敏捷)
2. 你只有一堆微服務,其他什么也沒有
在開始使用微服務之前,您已經進行了一些搜索研究:您已經確定微服務是“小型、松散耦合、自包含的軟件單元,它們通過 ReST 或其他協議相互通信。“ 或類似的東西。
這就是您所構建的。一堆“小”服務,它們都通過 ReST 相互通信。如果服務需要持久化數據,則它連接到數據庫。如果該數據需要在您的移動應用程序中呈現,則 ReST 端點會暴露給外部世界。如果另一個服務需要訪問該數據,則會添加另一個 ReST 端點。或者它可以使用移動應用程序使用的相同端點?或者它應該直接與數據庫對話?
換句話說,你有一個糟糕的設計,無法維護的混亂。每個微服務都有多種用途。依賴關系向各個方向發展(并且在某個地方有一個循環依賴等待你在生產中大吃一驚)。并且沒有辦法為不同團隊將擁有的不同服務劃清界限。
3.您無法對微服務分類
微服務并非都是平等的……或者至少,它們不應該是平等的。存在不同類型的微服務(通常稱為微服務構造型)以服務于不同的目的。這些類型的示例包括:
- 數據服務,僅負責與單個聚合相關聯的數據的存儲和檢索。
- 與多個數據服務進行通信的編排服務,以存儲與多個聚合相關聯的數據,或者讀回該數據并將其組合為更大的數據結構。
- Backends-for-frontends (BFFs),向特定客戶端發送數據和從特定客戶端接收數據。
- 消息總線使用者,使用和處理來自諸如Kafka之類的消息總線的消息。
并非所有組織都會使用所有類型(例如,GraphQL 減少了對前端專用后端的需求。)但是,在構建第一個微服務之前,組織應該創建將使用的類型目錄。
此外,該目錄應概述不同構造型之間的依賴關系。最好的方法是為您的架構定義分層層。任何給定的類型都屬于單個層。并且層之間的依賴關系僅在一個方向上流動。
這種方法的好處包括:
- 組織中的每個人都說同一種語言。
- 它使工程師不必在每次構建新功能時“重新發明輪子”,或者只是猜測他們需要構建哪些服務。
- 推斷任何給定微服務可能具有的依賴關系變得更容易。
- 它忽略了諸如“我的微服務應該多小?
- ”之類的問題。
- 以及“我應該創建多少個微服務?
- ”
4. 你正在更換整體中的一部分
好的,你已經確定了你的微服務印象:底層數據服務,中間編排服務,頂層BFF。你的微服務架構有一個深思熟慮的結構。
現在是時候開始分解單體應用并用微服務替換它們了。因此,不幸的是,您選擇了一種在團隊第一次嘗試拆分整體時很常見的方法:您決定拆除單體應用的一個水平層(例如數據訪問層),并用微服務取而代之。
這是沮喪和混亂的來源。
雖然看起來好像您正朝著正確的方向前進,但實際上您倒退了一大步。在每一次交互中,你仍然還保留有你的整體/單體架構,而且您必須將這個單體應用連接到您的新微服務,您需要處理新的網絡問題。你在單體應用中認為理所當然的事情(比如粗粒度的數據庫事務)需要仔細區分。測試將變得更加困難。部署將變得更加危險。
也許最糟糕的是,組織中的人們會開始懷疑這種微服務是否是個好主意。領導會看到所有這些時間和精力花費,但看不到任何好處。作為工程團隊,您當然會捍衛自己的努力。你會說,它在未來會得到回報。但暗地里,你們中的許多人也會懷疑這是否是正確的決定。
所以恭喜:您剛剛增加了應用程序的復雜性,并降低了其性能和可預測性。您增加了額外的故障點,并增加了系統的可觀察性要求。你已經完成了大量的一次性工作。你對整個努力的信心下降了。
- 團隊所有權自治
上述直接替換數據層方法違背了團隊所有權自治,掉數據層的方法會鼓勵您的工程組織簡單地制作整體數據持久層的小副本。當團隊構建其余的服務和流程時,這些服務幾乎無法使用。
借助微服務,各個團隊應該設計和構建他們需要的服務。他們可以查看他們的問題空間,并設計最能完成工作的應用程序、服務和流程。這些服務和應用程序——連同它們的底層數據庫模式——最終可能會與它們的單體應用程序大不相同。
(banq注:也就是說,使用數據層的服務層才更應該被切割成微服務,這種切割是根據康威定理的團隊結構決定技術架構的理論,只有首先切割團隊,才能實現微服務,最后切割數據層)
例如:您的公司應該有一個團隊負責在線注冊。這個團隊應該是跨職能的,包括建立新流程所需的任何人員:產品經理,設計師,移動工程師,前端和后端工程師,數據和安全工程師等。該團隊現在不僅擁有構建流程的自由在新堆棧中,還要重新發明流程中需要重新創建的任何部分。
5. 你有一個維護一堆“核心服務”的團隊
微服務的一大好處是各個團隊擁有自己的東西。他們構建、部署、監控服務,并在出現問題時修復它們。團隊知道他們擁有的服務的來龍去脈,并以彈性的方式構建它們(畢竟,當服務失敗時,團隊就會陷入困境!)
因此,本著這種精神,您組建了一個強大的“核心服務”團隊。該團隊擁有管理“共享”數據的微服務。可能被多個產品團隊使用的任何數據(用戶、產品等)都由一項核心服務管理。這些產品團隊只需進行同步調用即可獲取他們需要的任何“核心數據”。
讓我們退后一步問:為什么團隊要構建和維護自己的服務?一個主要原因是領域專業知識。團隊——尤其是跨職能團隊——通常擁有設計、構建和管理與其特定領域相關的服務和應用程序的綜合知識。這就是為什么團隊(或應該)圍繞他們提供的垂直功能組建:產品搜索;購物車結賬;帳單;等等。
相比之下,“核心服務”團隊不提供特定的領域知識。當然,他們知道如何構建微服務。
- 讓團隊管理他們使用的數據
每個垂直團隊都應該擁有自己使用的數據副本,而不是依賴“核心”服務領域。這個想法可能會導致一些讀者輕微的心臟病發作;畢竟,如何維護任何數據的單一真實來源呢?在大多數情況下,可以以最終一致的方式同步整個組織的數據。它的工作原理是這樣的:
- 某人在某個時候成為您的用戶之一;
- 例如,通過在線注冊流程(您可能還記得,由注冊團隊負責)。
- 在這里,關于用戶的基本信息被收集并存儲在注冊有界上下文中。
- 用戶還被分配了一個全球唯一的 ID。
- 這個新用戶的數據,連同他們新生成的 ID,然后被發布到一個消息總線,比如 Kafka。
- 屬于其他感興趣的團隊(例如直接營銷和客戶支持團隊)的服務使用來自消息總線的數據。
- 然后,他們可以自由存儲自己對新用戶的表示。
- 此外,這些團隊可以自由地使用任何其他信息來擴充他們的用戶數據。
- 例如,客戶支持團隊可能會收集和存儲用戶白天和晚上的電話號碼。
因此,不同的團隊對貴公司的“核心數據”保持自己的看法。當然,一些數據將駐留在多個視圖中。例如,不同的團隊可能會存儲用戶的名字和姓氏。如果該數據稍后在其中一個流中發生更改,會發生什么情況?簡單的。這些更改將發布到消息總線,與新用戶數據的發布方式相同。感興趣的團隊只需使用和處理這些更改事件,即可使他們的數據視圖保持最新。
這是否意味著您永遠不應該擁有任何“核心服務”?不必要。有一些有效的用例,通常在安全領域(例如令牌驗證、授權等)。但是,如果您發現您的組織擁有多個此類服務——尤其是核心團隊不具備特殊領域知識的服務——您可能想要改變方向。
相關技術教程:最全面微服務教程:SpringBoot + DDD + Apache Kafka實現最終一致性
6. 多個團隊“擁有”一個微服務
不久前,您的團隊開發了一個非常受歡迎的微服務。這個微服務有一些獨特的功能——假設它是一個復雜的作業調度程序——最初是為了解決特定的計費用例而編寫的。
當然,事實證明,其他團隊對復雜的作業調度程序也有自己 的需求。因此很自然地,他們沒有開發自己的作業調度程序微服務,而是將自己的東西塞進了您的服務中。
這個曾經由單個團隊編寫、擁有、修改、維護和部署的服務現在正在被修改、維護和部署。
您的團隊不再可以隨時更新和部署服務:突然之間,您必須在多個團隊之間進行協調以確保可以發布服務(實際上,您考慮將每周發布安排在周二早上。)您仍然是代碼所有者,因此您需要進行審核你一無所知的拉取請求。
換句話說,這個作業調度服務已經成為一個迷你單體。正是您首先試圖避免使用整個微服務的東西。
- 打破迷你單體
相反,每個團隊都應該構建和維護自己的作業調度程序。這樣,他們就可以在自己的時間表上部署更改。他們可以正確地審查自己的拉取請求。當他們的一項工作出現問題時,他們會確切地知道如何解決它。
現在,其他團隊想要利用您復雜的作業調度工作是可以理解的。您如何回答他們對重復您的團隊已經投入的工作的擔憂?
- 一方面,這是微服務概念的核心。
- 由于團隊擁有自己的微服務,并且這些微服務應該彼此解耦,因此肯定會有一些重復的功能。
- 另一方面,如果您團隊的作業調度器中確實有一些獨特的、有價值的代碼,那么您可以考慮將公共代碼提取出來以供重用。
- 這可以以框架或庫的形式完成(盡管大量使用內部框架/庫應該謹慎)。
- 另一種選擇是將作業調度程序作為基本Docker鏡像分發,允許團隊將自己的配置分層。
將開源技術應用于公司內部代碼庫的做法,已經變得流行起來。許多公司已經成功地使用了它。因此,您可能會問,這是否與這里給出的建議相矛盾?我們不能采用不同團隊在同一個微服務上工作的內部sourcing模型嗎?
事實上,內部sourcing可以工作……當它應用于真正共享的資源,如庫和模塊時。但是請注意,庫和模塊存在的根本原因是要共享的;它們真正歸多個工程團隊所有。這與微服務形成鮮明對比,微服務是(或應該是)各個團隊只擁有自己的權限。
7. 一個團隊構建微服務并將其交給其他團隊維護(研發與現場維護分離)
您的團隊需要構建一個新的微服務。事實證明,平臺團隊有一些備用周期。由于您的團隊正忙于完成其他一些工作,因此他們已被指派構建新的微服務。完成后,他們會將其交給您的團隊。
現在,您應該感覺到這不是一種理想的方法。當然,一個團隊將創建服務,一個團隊將維護它。但這些團隊應該是一體的。如果您的團隊將擁有該服務,那么首先應該創建該服務。
- 您的團隊擁有領域專業知識。
- 是否有其他團隊足夠了解您的業務以正確構建您的服務?
- 平臺團隊知道一旦服務在生產中運行時,他們就沒有麻煩了。
- 即使以最大善意猜測:
- 他們真的會盡一切努力確保服務具有彈性嗎?
- 并保證在生產中很容易調試嗎?
- 如果需要,他們是否會推遲截止日期以便這樣做?
- 即使在最好的情況下,也會有一個低效的“交接”期,在此期間,您的團隊需要與平臺團隊坐在一起,以演練服務并了解它。
當然,這一切都是經驗法則。規則是用來打破的。有時您會真正希望在自己的有界上下文中實現異步通信,而有時則需要跨綁定上下文進行同步通信。
9. 只有當您的客戶告訴您時,你才發現您的服務調用失敗了
你的公司已經定義了它的微服務教條印象:您的團隊已經弄清楚它需要構建哪些微服務并設計了它們的交互。您已經構建了服務,測試了它們,并將它們部署到了生產環境中。
那么……他們在生產中的表現如何?
事情會不時發生故障,尤其是在分布式環境中。這不是if 的問題,而是when 的問題。當他們失敗時,你最好是第一個知道這件事的人。
這意味著不僅僅是用日志消息散布您的代碼。在將單個服務部署到生產環境之前,您應該確保擁有儀表板,可以近乎實時地洞察服務的重要指標,例如:
- 錯誤率和成功率
- 收到的費率或請求,或消耗的消息(取決于服務的目的)
- 性能指標,例如延遲等
這些儀表板對于保持對生產中服務行為的認識至關重要。當然,您不會經常盯著這些儀表板;它們通常在部署等高風險時期很有用,或者在您對持續問題進行故障排除時。因此,設置警報以在出現問題時立即通知團隊成員更為重要。
監控和警報本身就是一個主題。但在使用微服務之前了解這一點很重要。
10. 你期待完成
這是一段漫長的旅程,充滿挫折和成功。但是,您為那個幸運的日子存下了一箱香檳:您的組織完成向微服務遷移的那一天。
你不太可能真正到達那一天。通往微服務的旅程永遠不會真正結束。
首先,它在現實世界中很少真正發生。在所有遷移微服務的公司中,很少有人用微服務替換所有遺留系統。隨著越來越多的應用程序轉向微服務,就會出現收益遞減點。構建新服務和淘汰遺留應用程序的努力不再值得。微服務的要點是解耦團隊并為他們提供自治權。一旦貴組織的大多數團隊擁有這種自主權,替換遺留代碼的價值和愿望就會減弱。
其次,微服務帶來了敏捷性和變化能力。隨著您進一步前進,您將從過去的錯誤中學習。你會發現新的模式。更新的技術將會出現。
因此,如果您一直等到工作完成的那一天才打開香檳,那么您很可能永遠不會打開它。此外,如果您將轉向微服務視為一項重大(我敢說,整體)努力,假設有一天您會“完成”,那么您將冒著讓自己陷入困境的真正風險永遠更糟的狀態。
相反,要認識到微服務代表著一個持續的旅程,它應該由一系列的小勝利組成。在每一步之后,您都應該處于比開始時更好的位置。這樣,您將始終朝著正確的方向前進。
總結遷移基本原則:
- 微服務是關于團隊自治的
那里的許多文獻都會吹捧微服務的技術優勢。但實際上,微服務的最大好處在于它們如何使團隊能夠靈活、自主地運作。
所以在每一步,問問自己:你的團隊是否變得更加自主?他們是否對自己的命運有更多的控制權?或者他們和你開始之前一樣耦合和相互依存?
- 垂直思考,而不是水平思考
我們中的許多熟悉單體應用和微服務新手的人傾向于在水平層中考慮我們的技術和我們的組織。我們將單體應用分為表示層、服務層和持久層。同樣,我們將我們的工程組織劃分為設計師、前端工程師、后端工程、平臺等。
然而,為了獲得微服務的好處,我們想要垂直思考。我們應該圍繞功能(例如,注冊或購物車/結帳)組建我們的團隊,而不是圍繞特定技術架構(例如后端工程)組建團隊。借助微服務,這些跨職能團隊可以構建滿足其需求的應用程序和服務。
- 微服務是一個持續的旅程
重要的是要了解,從單體應用遷移到微服務需要花費大量時間和精力。您的組織需要保持士氣高漲和決心穩定。您不能投資于“暫時”使事情變得更加困難并使您陷入比以前更糟糕的境地的舉動。取而代之的是,您的微服務之路需要取得小勝利,以提醒每個人他們正在朝著什么方向努力。