你真的瞭解微服務嗎?

作者 | Charles Mahler

譯者 | 平川

策劃 | 萬佳

本文最初發佈於 freeCodeCamp 博客,由 InfoQ 中文站翻譯並分享。

過去幾年,微服務已經從一個誇大其詞的流行語變成了一個是個軟件工程師就應該瞭解的東西。

根據 2020 年 O'Reilly 開發者調查:

隨着微服務生態的成熟,採用微服務越來越容易,上述數值將繼續增長。

這不是說,爲了找份工作,你要成爲微服務專家,但至少,理解基本原理還是有好處的。

事實上,關於微服務的基礎知識並不難理解。最大的問題是,與此相關的大部分資料都是爲了譁衆取寵,而不是爲了讓讀者掌握相關知識。

另一個原因是,微服務沒有一個準確而具體的定義。於是就出現了大量語義上存在重疊的定義和術語,讓試圖瞭解微服務的人陷入困惑。

在這篇文章中,我將去蕪存菁,重點介紹微服務的核心概念。我將使用各種真實世界的例子和類比,幫助你理解相關的抽象概念和思想。本文將介紹以下內容:

1 如何理解微服務:以自主創業做類比

假如你是一名軟件工程師,你決定通過自主創業來賺錢。一開始,你有一些客戶,事情進展很順利。你把大部分時間都用在編寫代碼上,客戶也很滿意。

但是,隨着時間推移,業務規模擴大,你的速度慢下來了。你把越來越多的時間用在客戶服務、回覆郵件、爲之前的客戶做一些小的修改以及其他一些無助於增加收入的事情上。

你意識到,作爲一名軟件工程師,你並沒有以最佳方式利用好自己的時間,因此,你僱了一名員工,專門負責客戶服務。

隨着業務規模繼續擴大,你僱傭了更多具有專門技能的員工。你僱傭了一名營銷人員,專注於吸引新客戶。你增加了項目經理、軟件工程師,最終又增設了 HR 部門來幫助你管理這些員工。隨着業務規模的擴大,所有這些都是必要的,都不是你一個人能完成的,但是,不可避免的還有成長之痛。

有時候,客戶或部門之間會存在溝通上的不暢,而客戶會因爲細節上的不足感到沮喪。企業要承擔支付員工工資的直接成本,團隊之間會存在內部競爭,還會有其他隨着企業發展而出現的問題。

這是軟件公司從單體轉向微服務的一個多少有些代表性的例子。一開始一個人做所有的工作,然後逐漸變成多個專門的團隊一起來實現公司的共同目標。

這非常像技術公司從單體遷移到微服務架構。雖然這些例子與微服務不能一一匹配,但所要考慮的一般問題是一樣的:

1、擴展——理想情況下,你希望可以快速僱傭新員工,實現生產力的線性增長;

2、溝通——增加員工意味着增加組織的溝通協作成本。在這個遠程工作的時代,企業有許多辦法可以實現高效的溝通;

3、專門化—— 讓組織中的某些團隊可以自主解決問題,採用最有效的方式,而不是在所有情況下都遵循同樣的標準程序。有些客戶可能會有不同於其他客戶的需求,因此,讓團隊在處理事情時有一定的靈活性是有好處的。

2 如何從單體轉到微服務

理解上圖有助於我們瞭解過去。傳統上,軟件設計採用單體風格,所有東西都在一個應用程序中一起運行。和生活中的其他事情一樣,這種應用程序設計也是優缺點並存。單體並不一定差——許多微服務倡導者實際上也建議從單體入手,如果沒有問題,就一直沿用單體即可。如果遇到了問題,就可以隨着時間的推移自然而然地將單體拆分成微服務。

3 單體架構的優點

初始開發速度快

剛開始時,在一個小團隊裏,單體的開發速度相當快。這是因爲項目小,每個人都瞭解整個應用,事情進展非常順利。團隊成員非常清楚各種功能是如何協同的,新特性的實現速度很快。

部署簡單

由於單體只有一個工作單元,像測試、記錄日誌這樣的事情都很簡單。與部署多個獨立的微服務相比,構建並部署一個單體更簡單。

4 單體架構的缺點

雖然單體架構早期有諸多好處,但隨着公司發展,採用單體架構的應用程序經常會遇到一些組織和技術層面的問題。

模塊緊耦合

爲了便於組織管理,大多數有單體應用程序的公司,都試圖根據應用場景將單體合理地拆分成功能模塊。考慮下諸如身份驗證、評論、用戶和博客帖子這樣的東西。

問題是,這需要嚴格的工程紀律保障才能長期保持下去。當最後期限臨近時,許多已有的規則經常被拋諸腦後。這會導致關鍵時刻走捷徑,產生關聯關係複雜的代碼,技術債務隨着時間推移不斷增加。

現實世界的例子——遵守單體開發的紀律非常像堅持有規律的運動或節食。許多人都是那樣,在開始幾周很興奮,可以堅持節食,但最終,生活妨礙了節食計劃,你又退回到了習慣的狀態中去。

在單體中強制實現松耦合就是這樣,當時間緊迫時,很容易禁不住誘惑偷工減料。

新人蔘與困難

新員工需要花更長的時間才能具備生產力,因爲他們需要先理解單體中各個相互關聯的部分是如何協同工作的,然後才能冒險修改應用程序的某個部分。

我們肯定聽說過,新員工花了幾個月的時間才真正熟悉了一個大型代碼庫。而且,人們總是會有潛在的擔心,就是怕推送新代碼會弄壞整個應用程序。

與現實世界對比——培訓某個人做一件事,如釘釘子 vs 培訓某個人做建築工地上的每一項工作。

把有關整個工作的所有東西都教給一名新入職的員工,無疑會增加僱傭新員工的成本。

資源需求衝突

在一個單體中,不同的模塊可能有不同的硬件需求。有的任務可能是 CPU 密集型的計算,有的可能需要大量的內存。但是,由於整個應用程序運行在相同的服務器上,所以你無法使用針對特定任務的硬件。

現實世界的例子——某些類型的車輛更適合某些類型的任務。

如果你想來一場公路旅行,那麼一輛具有絕佳燃油經濟性的汽車將是最佳選擇,因爲可以幫你節省油錢。如果你要搬到新公寓,那麼空間更大的車輛無疑更合適,因爲可以減少來回趟數。

一個 Bug 就可以讓整個應用宕掉

由於整個應用程序是一個部署單元,所以任何團隊都有可能在無意間製造一個 Bug,使得整個單體宕掉。

現實世界的例子——爲了防止一個地方漏水使整艘船沉沒,如果某個區域開始大量進水,就會使用隔板將其封住。

微服務的工作方式類似——每個服務都是獨立部署的,這樣可以減少一個 Bug 搞宕整個應用的機會。

限制了試驗

在構建單體時,你差不多就困在了用來編寫單體的編程語言生態中。一個簡單的例子是低級編程語言和高級編程語言的取捨。

在微服務架構中,如果某個服務擴展困難,那麼你就可以考慮使用一種性能更好的語言如 C++ 或 Go 重寫它。而對於其他並不需要太關注性能的服務,你就可以使用像 Python 或 JavaScript 這樣更高級的語言來提高開發速度。

單體架構讓團隊看不到其他解決問題的方案。當你只有一把錘子在手時,看什麼都是釘子:

與現實世界對比——披薩很棒,但你應該不會希望餘生每餐都喫披薩。

而且,在某些情況下,與其他東西相比,做個披薩來喫並不方便。有時候,隨便喫點快餐或喫點更健康的東西就不錯。

部署會變得很慢

在上面提到的單體架構的優點中,有一個會慢慢變成缺點。對於大型單體來說,整個應用一起部署會成爲問題,因爲部署整個服務會需要很長時間。這會降低團隊迭代和修改應用的速度。

每次做個小更改,都得等着應用構建、部署,然後測試。

現實世界的例子——你的夢想是做出世界上最好的曲奇餅乾。達成這個目標的最快方式是儘可能多的測試,並逐步調整和改進配方,直至它趨於完美。

如果你只有一臺烤箱,那麼與有 10 臺烤箱相比,你測試不同曲奇配方的速度就會慢許多。

5 微服務的優點

現在,你已經知道了單體架構的優缺點,讓我們看下微服務。

提升開發速度

因爲部署的不再是單體,所以團隊可以更快地增加新特性。各團隊有自己單獨的發佈計劃,不用再過多考慮與其他團隊的協同。

只要外部接口(提供給其他微服務用於和本服務交互的接口)保持不變,開發團隊可以根據需要使用另一種編程語言完全重寫系統。

各個服務單獨部署的另一個好處是,每個構建的規模變小,速度變快。也就是說,僅僅因爲構建變快就可以提升迭代速度。

現實世界的例子——當你從餐館購買食物時,只要食物口味好就行,你並不關心後廚有什麼變化。

也許他們有了新烤箱或炸鍋,但只要食物的口味不變,就沒有關係。外部消費者唯一關心的是最終產品。

新人上手更快

新員工只需學會一個簡單的系統就可以開始做出貢獻了。隨着時間推移,他們可以繼續學習更多關於整個應用程序的內容,但不必馬上就學。

現實世界的例子——裝配線通過把事情分解改變了生產方式。每一名員工都不必知道如何從頭開始創建一個完整的產品,他們只需要學習他們參與的那一部分。這可以節省新員工培訓時間,更有利於企業發展。

容錯性

雖然微服務經常會依賴於其他微服務來完成工作,但設計良好的微服務架構會內置冗餘和失敗保護機制,可以防止其他服務宕掉時導致整個系統失敗。

通常,這包括請求重試,而且隨着請求次數增加,請求之間的等待時間也會增加,或者如果服務不可用,就返回一個默認的備用值。

現實世界的例子——如果 Netflix 的推薦服務中斷,那麼把完整的故障信息返回給用戶是沒有意義的。

因此,在這種情況下,Netflix 會默認返回當前流行的影片,而在後臺則繼續重試訪問推薦服務,直到它返回爲用戶客製化的觀影建議。

擴展靈活

由於每個服務都是單獨部署的,所以每個服務都可以單獨複製和擴展。如果是單體,那麼公司就只能擴展整個應用程序,即使只有一個特性的流量超出了平常。

在微服務架構中,公司可以單獨擴展需要處理更多流量的服務,這樣更高效,也更省錢,因爲這減少了資源浪費。

現實世界的例子——考慮下亞馬遜的網購星期一,訂單會比平時多,但大多數人其實已經提前選好了他們想要的東西,並放到了購物車裏。

所以,訂單服務的流量會比平時高,但搜索服務及其他特性的訪問情況可能和平時差不多。

如果一個服務特別消耗某種資源,這會尤其有用,因爲可以針對這種任務使用專門的硬件。

如果一個服務需要大量的 CPU 資源,但需要的內存不多,那麼爲了節省成本,公司就可以不購買通用服務器。使用純單體的公司就別無選擇,只能使用通用服務器了。

6 微服務的缺點

微服務架構還遠稱不上完美。從單體轉到微服務緩解了一些問題,但也帶來了新問題。

增加整體複雜度

雖然單個的服務更容易理解,但整個系統本身更加複雜了。這種複雜性催生了像 Docker 和 Kubernetes 這樣的工具,爲的是儘可能地把這種複雜性抽離出來。

這些工具的目的是讓軟件工程師可以和以前一樣專心構建特性,而不必考慮其他事情,比如它們在後臺是如何運轉的。

通信

在微服務架構中,其中一個最大的問題是明確微服務之間彼此如何通信。

用戶發起的一個外部請求,可能需要多個服務協同來滿足。讓我們以在線下單爲例來看看這個過程。

在上述步驟中,其中任何一個服務失敗都會導致整個過程失敗或引發客戶不滿,很快就會積累一批憤怒的客戶。

在微服務架構中,處理所有服務之間的交互,應對局部失敗,是一項很大的挑戰。

數據處理

關於微服務,其中一項最大的挑戰是處理跨多個服務更新數據的請求。

在這個過程中,如果請求的一部分失敗了,一個服務更新了數據,而其他服務沒有更新,怎麼辦?不能說因爲服務宕掉了,你收了用戶的錢,用戶卻沒有收到貨。

在單體中,如果出了什麼問題,你可以利用 ACID 事務回滾數據庫更改。但在微服務架構中,要複雜得多,這會涉及跨服務的分佈式事務。

開發環境

大多數工具是針對單體架構而設計的,在開發微服務架構應用時一般會更難一些。

測試需要能夠模擬與其他服務的交互,調式也更難,因爲事情不是發生在單個進程中,日誌必須能夠跨多個服務進行記錄。

即使像 “跟蹤一篇博客爲什麼加載慢” 這樣簡單的事情,其困難程度也會超出你的預期。

假如你從分析工具中看到,頁面加載博文突然需要 5 秒了。在單體中,這個問題很容易跟蹤,但在微服務架構中,你需要使用專門的工具來跟蹤外部請求,因爲它們是由不同的服務處理的。

7 小結

希望本文可以幫助你瞭解什麼是微服務以及爲什麼要採用微服務,並對微服務的工作原理有一個直觀的認識,指導你瞭解底層的技術細節。

查看英文原文:Microservices Architecture – Explained in Plain English

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/TdigEcro9Sg-RibW1wQ9Sg