這些公司爲什麼放棄微服務?

微服務正在統治世界,甚至有可能正在成爲新的默認選項。

O’Reilly 調查了 1283 個企業,有 52%的受訪者表示他們正在使用微服務進行軟件開發。其中超過 28%使用微服務超過三年,超過 55%使用微服務的時間爲一到三年。O’Reilly 還指出企業對微服務的興趣可能達到或接近頂峯。

這幾年,有無數的中小團隊在微服務上陷入了掙扎。微服務有好處但也存在弊端和風險,業務不斷髮展,微服務也更加複雜,一些企業權衡利弊後甚至選擇了退回單體架構。今年,有好幾個公司總結了他們放棄微服務實踐的事情。

Uber 支付體驗平臺放棄了微服務,轉而使用了合理規模服務。4 月 6 日,Uber 支付體驗平臺的工程經理 Gergely Orosz 發佈推文表示其團隊的架構方向已經發生了變化,放棄微服務,轉而使用宏服務。

爲什麼會做出這樣的選擇呢?Gergely Orosz 表示:“最早,Uber 通過構建微服務來完成很小的需求或功能,以至於出現了很多由一個人構建維護的微服務。這些微服務的存在給我們帶來了新的複雜性和挑戰,例如監控、測試、持續集成 / 持續交付(CI/CD)、服務級別協議(SLA)、跨所有微服務的庫版本(安全和時區問題)等等。”

因此,在創建新平臺的時候,Uber 支付體驗團隊對新服務進行了更加深思熟慮的規劃:不再只是完成一件事,而是使其服務於一項業務功能,由 5-10 個工程師負責維護。Gergely Orosz 把這樣的服務規劃稱之爲宏服務。

要在正確的時間選擇正確的解決方案來構建產品。

Botify 是一家從事 SEO 優化的公司,其平臺於 2012 年在 Python/Django 技術棧上創建。2016 年初,整個 Botify 平臺都是通過 Django 應用程序的負載均衡集羣提供服務。

2016 年年底,Botify 工程團隊想讓工程師和產品經理擁有更多的局部所有權,從而可以快速輕鬆地將他們的產品和技術棧投入使用。爲此,他們決定將他們的 Django 應用程序拆分爲微服務。當時,他們的團隊大約爲 15 人。他們從身份驗證和授權入手實現第一個微服務,將 Django 應用程序當前的一部分功能轉移到微服務中。微服務模塊也需要和其他的 Django/Python 單體模塊進行通訊。

Botify 的平臺是一個企業級 B2B 服務,幫助網絡上最大的網站改善他們的 SEO,主要挑戰在於對客戶數據的分析。處理用戶相關數據的微服務架構旨在服務於高流量的 B2C 平臺,而 Botify 的挑戰在於動態地聚合數以 GB 的 SEO 數據,使其在幾秒鐘內可用。對大約一萬名客戶的元數據以毫秒爲單位進行響應,這項任務不需要高度可伸縮的微服務架構。恰恰相反,Botify 的後端到後端通信減慢了這些簡單的檢索過程,花費了更多的時間。

鑑於每天都要在 JavaScript 身份驗證後端和 Django 模塊之間頻繁地來回切換,權衡架構的優缺點以及潛在的遷移成本後,他們做出了大膽的選擇,將身份驗證後端重新加入到 Django 單體中。

Botify 於今年 2 月停用了微服務。其團隊負責人 David Wobrock 表示:“每一種技術都自有其用途,但我們相信,要在正確的時間選擇正確的解決方案來構建我們的產品。如今,我們不必來回切換了,也不用維護兩個後端了,顯然,我們已經從中獲益。“

“我們公司也從單體轉向了微服務,但最後在二者之間找到了一個平衡點。”

在 2017 年的時候,辦公管理軟件公司 Managed by Q 的技術團隊大概有 20 名工程師,應用程序是一個部署在 ECS 上的 Django 單體。爲了趕上現代化開發實踐的步伐,他們開始轉向了微服務架構。

但隨着微服務數量的增長,事情不像之前那麼順利了。

每多一個新服務,就會增加一些基礎設施。比如,一個 ECS 服務、一個 Postgres 實例或一個 RabbitMQ 實例。CI/CD 的配置也會增加,還需要進行第三方服務(比如 Rollbar/Sentry)配置。依賴也需要更新,而且需要更新依賴的地方越來越多。基礎設施團隊在項目上花了很多時間,爲每一個服務重複着枯燥無味的工作。而且小型的服務容易被人忽略,在運行起來之後,基本上會被擱在一邊,最後就會過時。

如果服務邊界沒有搞清楚,還會顯著降低功能的開發速度,這是微服務的一個很大的風險點。開發一個跨多個服務的功能需要做更多的工作,而重構一個跨多個服務的功能是一個噩夢。如果服務邊界很清晰,大部分項目只會影響到一個服務。但是,對於初創公司來說,它們的發展方向是不可預測的。一個產品的兩個部分在一開始可能是完全獨立的,但一年之後可能會變得緊密耦合起來。所以,要完全清晰地定義服務邊界不是件容易的事。

最後,在轉向微服務兩年之後,他們開始合併微服務。一些微服務被合到了單體中,其他的則合併成較大的服務。在一年中總共移除了 9 個微服務。大小合理的服務承擔着相當大的責任,大多數功能開發都可以在單個服務中完成。

不能當然地認爲微服務就是正確的選擇。

微服務已經被這代人當成銀彈,不過,上面提到的這些企業已開始用更挑剔的眼光來看待它。這些例子中,他們認爲轉向微服務的工程開銷太大,不值得。而這樣的案例還有很多。

每個系統實現都會有一些錯誤的選擇。但是,他們所犯的最大的錯誤與他們的微服務實現無關。他們所犯的最大錯誤是在只有 20 名工程師的環境中實現了幾十個微服務。

如果你認爲,“在一個只有 20 名工程師的團隊中實現大量的微服務簡直是瘋了!”那麼,我同意你的看法。但這種情況隨處可見,這至少表明沒有一種單一的架構模式適合所有的人。

我從三年前就開始寫這篇博文了,期間,我無數次聽說有中小型團隊在微服務上陷入了掙扎,現在,我終於準備好發表了。我寫這篇文章不是因爲我討厭微服務,而是因爲我擔心微服務正在成爲新的默認選項。“你不用微服務嗎?那麼顯然,你沒把軟件工程當回事。”人們不再做決定,他們只是想當然地認爲微服務就是正確的選擇,我認爲這是有問題的。

規模決定一切

你的系統有多少人在開發?五個?十個?五十?一百?還是一千?如果你的應用程序、平臺、應用程序套件或其他任何東西,有超過 500 人在開發,那麼我認爲,你大可以放心地關掉這篇博文並繼續前進。你們的問題不是我們這裏要討論的問題。但是,如果你的應用程序開發工程師不足 100 人,那麼請別走,我們聊一會兒。如果你的情況介於兩者之間,那麼這就要看實際情況了,也請不要走開,看看是否能發現一些有用的東西。

我職業生涯的大部分時間都服務於做小東西的公司。我在大公司做過不少諮詢工作,但我工作過的大多數公司(或者是部門)都總共只有不到 100 名軟件工程師。通常,這類工程組織有一個共同的關注點:創建可靠且穩定的系統,爲業務交付價值——所有這些都需要藉助緊張的工程資源。

我所處理的問題都不是在谷歌、Facebook 或 Uber 那種規模上。在有些人看來,我似乎不知道自己在做什麼,但就我個人而言,我認爲這是一種資產。我認識的在這類機構中工作的人都很聰明,但他們不是魔法師。

在一個大型工程環境中工作,意味着用幾乎無法估量的工程資源大規模地解決問題。通常,他們有大量的內部工具和庫可以使用,這使他們能夠編寫大規模的軟件。與來自大型工程環境背景的人交流得越多,我就越意識到,對於我們這些人來說,在一家初創企業或中小型企業中,與由 5 名、10 名甚至 50 名工程師組成的團隊打交道是多麼困難。

建議是要看上下文的

在如此大的規模下,溝通和協調是迄今爲止最大的挑戰之一,這是有道理的。減少團隊之間的依賴關係,或者讓應用程序擴展到每秒處理數百萬個請求,規模這麼大,這樣的需求完全值得付出如此巨大的工程開銷。

但是,對於中小型企業,我經常聽到這樣的建議:

  • 你需要重新構建一個更現代化的軟件棧;
  • 你應該使用擴展性更好的數據存儲;
  • 你的數據工程團隊可以切換到 Kafka 嗎?
  • 你應該重構成一系列的微服務;
  • 你需要用 Go、Rust 或其他高可擴展的語言進行重寫。

通常,這些中小型團隊發現,僅僅是滿足特性請求和提供支持就很困難,更不用說考慮重寫整個應用程序了。這個建議合適嗎?當然,在很少一些情況下可能是合適的。但是,有小企業和創業公司一再告訴我,他們從導師或顧問那裏聽說過這些。

是不是有的建議聽着很熟悉?

當你需要應對一個小型團隊和一個大型應用程序時,這可能會讓人膽怯。你會感覺到各種壓力,協調特性發布,隨着系統複雜性的增長開發速度下降,你開始閱讀很多文章,瞭解如何將應用程序分解成很多小塊,從而幫助你降低複雜性,提高部署頻率,簡化開發工作。

所以,你決定從只有 20 人的工程師團隊裏抽出一大部分人,和少量的工程承包人員一起,在接下來的兩年裏重新規劃設計你的應用程序,拆分你的系統,並構建出幾十個微服務,可能還有一些微前端。在新構建的應用程序上線後,你很快就會發現,部署確實越來越頻繁。每個微服務的代碼庫都很小,推斷也比較容易。小型的更新和 Bug 修復可以更快地完成、測試和上線。你對自己說:“太棒了!這肯定會提高開發團隊的開發速度!”

新挑戰

但是,接下來的幾個月裏,你開始遇到一些挑戰。

協調

每當需要進行較大的更改時,你就會發現自己需要更新許多服務,並且要協調這些服務的發佈。當你向同事提起這件事時,他們總是說:“你弄錯了。你的服務在邏輯上應該是分離的。”邏輯上分離,聽起來很好,但是,你已經將系統拆分成許多小塊,所以這些小塊之間有很多依賴關係。有人曾經說過,如果你的服務之間有一堆依賴關係,那麼你的拆分邊界就有問題,但是,除了大幅減少微服務的數量外,你並不知道其他的拆分方法。

數據一致性

你還會注意到,出現了一些數據一致性的新問題。看起來,應用程序中一些過去在單個操作中完成的操作現在被拆分到幾個不同的服務中,其中一個服務有一些寫入失敗。同樣,你的同事會告訴你,這樣做是不對的,但是,將庫存服務與訂單服務拆分成單獨的服務似乎是正確的,是符合微服務的精神的。你告訴自己,“也許,我們需要着手設計跨所有這些操作的多階段提交,或者我們需要構建工具來確保數據一致性。”再一次,這讓你覺得會明顯增加一些工程複雜性和開銷。

性能挑戰

性能問題也開始悄然出現——應用程序中的一些頁面需要調用六個服務來呈現,加載時間很長。看起來,你需要爲其中一些服務實現一個內部緩存層,以加快頁面呈現速度。簡單的緩存層不會特別麻煩,只是需要再添加一層。

分佈式跟蹤

隨着時間的推移,你還會開始注意到,團隊記錄的處理某些 Bug 的時間顯著增加。當你與團隊討論這個問題時,他們會說,某些問題在系統中很難定位。即使他們找到了,也很難再現它們,因爲在工程師的機器上讓多個服務進入同樣的狀態會是一項巨大的挑戰。你默默地記了下來,你需要從整體上做個規劃,以便提供更好的系統級可跟蹤性,這樣,你就可以看到請求在整個系統中的流轉過程。又多了一個待辦事項。

重複

現在,設計和構建某些比較大的特性需要花費更長的時間了。它們需要多個不同的服務來實現不同的功能,並在不同的數據存儲中協調更改。你會發現,自己在不同的服務中複製了某些業務操作的邏輯,儘管你已經盡了最大的努力來保證每個服務在邏輯上是獨立的,但是,你沒法完全做到這一點。這給錶帶來了各種不同的風險,因爲現在需要在服務之間保持業務邏輯的一致性。這是否意味着創建共享服務?手動保持邏輯同步?一聲嘆息。

安全面

另一個關鍵點 CVE 呢?謝天謝地,你花時間在構建過程中引入了工具,使你能夠知道哪個服務受了影響,因爲爲所有這些服務打補丁是非常困難的。手工審計每一個服務將是一項艱鉅的任務。儘管如此,因爲一個 CVE 版本而部署 24 個服務是一種你沒有真正考慮到的痛苦。

報表挑戰

如果將數據拆分到多個數據存儲,一些查詢就會變得非常複雜。因此,你聘請了一些顧問來幫助你構建一個專用的數據倉庫並創建一個 ETL 過程,將其轉換爲讓你的團隊可以輕鬆生成報告的形式。這種設置提供了一些預期的優點,但是,現在每次進行重要的模式更改都必須同時維護 ETL 過程。又多了一件事要處理。

穩定性

最後,穩定性開始出現問題。其中一個服務有點不穩定,在訪問它時會導致系統的其他部分掛起。現在,你看到的不是拋出的錯誤,而是請求靜靜地阻塞在那裏,直到失去響應。你知道,你的團隊沒有花足夠的時間來確保服務之間良好的容錯能力,因此你意識到,可能需要使某些交互異步進行,這將進一步增加工程開銷。

這非常令人沮喪,因爲你的團隊做了大量的研究,並試圖遵循所有可接受的模式來實現良好的微服務,但這種轉變帶來的開銷似乎並不值得。是的,單個服務的開發和部署更容易,但是,系統整體的複雜性高了許多。其中一些痛點可以通過額外的工程和一些更好的模式來緩解,但是,這就違揹你最初的目標了——你應該提高速度,用更少的資源做更多的事情,而不是增加系統的工程開銷。也許你在尋找靈丹妙藥,並做出了一些輕率的決定。

考慮下你面臨什麼問題?

也許你已經經歷過一些這樣的痛苦,並且深有感觸,或者你轉到了微服務,這對你的團隊來說是一個巨大的進步。在很多情況下,都有必要拆分出一些服務,但這完全取決於你面臨的問題。

你的痛苦是爲了有效地協調多個團隊對同一個單體應用程序所做的更改嗎?你的痛苦是否無法通過其他策略(如基於主幹的開發)來解決?你可能需要將其拆分,創建一些服務,並考慮微服務的意義所在。

你是否感到非常痛苦,因爲你那個有着數百萬行代碼的龐大單體需要做出一些犧牲並需要幾天的時間來部署?你需要把它拆分並開發成服務。

在你的應用程序中,是否有大量不相關的功能混雜在一個系統中?你可能需要一些服務,或者更小的應用程序。

你那擁有 30 名工程師的團隊是否深陷複雜性,開發速度很低,而大家都把原因歸咎於單體應用程序?你可能需要首先關注一個更好的單體,然後再考慮遷移到一些服務或一組較小的應用程序。

正如 Simon Brown 曾經說過的那樣:“如果你不能構建一個結構良好的單體,你憑什麼認爲微服務就是答案?

複雜性被轉移,但並未被消除

通過採用微服務或微前端,你是在轉移複雜性,而不是消除複雜性。在一些地方,這種轉變是值得的,但是,如果你的系統不夠大,你的團隊成員不夠多,而你面臨的問題不是來自於協調大量的開發人員,那麼將應用程序拆分成很多小塊可能會弊大於利。

我並不是說,小型團隊不應該把業務分解爲大小合理的服務,也不是說你不應該將那些功能過多的應用程序拆分。但多年來,我看到太多的人提出這樣的建議:把你的系統分解成很多很多的小塊,就能神奇地解決你所有的問題。

你需要清楚地瞭解你的系統所面臨的挑戰,看看整個團隊不斷增加的速度是否可以抵消構建分佈式系統所帶來的額外複雜性,然後再做出決策。如果你有證據證明這種取捨是值得的,那麼根據你的業務領域和團隊規模來拆分出合理的服務。務必要非常關注微服務的最佳實踐,否則你最終將構建一個分佈式的單體,這將是最糟糕的結果。

請注意,本文還沒有涉及從單體遷移到微服務的複雜性,不要低估了這種複雜性。這是一個需要非常謹慎的過程,並且應該增量地完成。

嚴格考察,謹慎行事

我建議你嚴格地考察權衡。考慮一下,你的團隊是否會從中受益,然後從小規模實驗入手,拆分出一些服務,看看效果如何。克服挑戰,覺得有意義再繼續前進。然後,重複上述過程。我知道,這可能與如今科技行業“快速行動,改變一切”的理念不符,但你最終會爲自己採取了慎重的做法而高興。

英文原文:

Gasp! You Might Not Need Microservices.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章