2018年微服務將瘋狂至死

banq發表於2018-01-16
本文是Dave Kerr發表的一篇微服務批判性文章,他認為複雜性是導致微服務將死的一個重要原因,實際上微服務本來是解決複雜性的,將牽一動百的單體架構變成很多獨立發展的服務,相互隔離,複雜性關鍵是因為隔離不清還是現實世界根本無法隔離分清或者沒有能力去隔離?其實單體系統最大問題是單點風險,而微服務化解了單點風險,但是這種化解是依靠多點替代單點,當然這個多點粒度也不能太細,否則如果從單點邏輯角度去看微服務,會覺得相當複雜, 當然關鍵是切分以後如何再簡單方便地拼起來。

下面是其原文的大意翻譯:

微服務在過去幾年成為一個非常受熱門的話題。“微服務瘋狂”就像這樣:

Netflix在DevOps上非常棒,Netfix做微服務。因此:如果我做微服務,我應非常擅長devops。

很多情況下,為了採用微服務模式我們付出了巨大的努力,根本不知道其成本和收益是否適用於當前問題的具體情況。

這裡我將詳細描述微服務是什麼,為什麼這種模式非常吸引人,還有一些他們提出的關鍵挑戰。

如果你正在考慮微服務是否是適合你的模式,我會用一系列簡單的問題來結束這個問題。問題在文章的最後。


什麼是微服務,為什麼如此受歡迎?
讓我們從基礎開始。以下是一個假想的影片共享平臺的實現方式,左邊是一個單體的,右邊是微服務的形式:

影片共享平臺 vs. (微服務: 上傳服務 流服務 轉碼服務 下載服務 推薦服務 訂閱服務)

兩種架構的區別在於第一種是單一的大單位,一塊巨石。第二種是一組小的,具體的服務,每個服務都有特定的角色。

微服務有很多潛在的好處:

1.獨立開發:小型獨立元件可由小型獨立團隊構建。一個小組可以改變“上傳”服務,而不會干擾“轉碼”服務,甚至不知道這個服務。瞭解元件的時間大大減少,開發新功能也更容易。

2.獨立部署:每個單獨的元件都可以獨立部署。這樣可以更快的速度和更少的風險釋放新功能。“Streaming流服務”元件的修復或功能可以獨立部署,而不需要同時部署其他元件。

3.獨立的可伸縮性:每個元件可以彼此獨立地進行縮放。在繁忙時段釋出新的節目時,可以放大“下載”元件處理能力,以處理增加的負載,同時不必擴大其他每個元件處理能力,這使得彈性縮放更加可行並降低了成本。

4.可重用性:元件實現一個小的,特定的功能。這意味著它們可以更容易地適用於其他系統,服務或產品。“轉碼”元件可以被其他業務部門使用,甚至可以變成一個新的業務,也許為其他組提供轉碼服務。

在這個細節層面上,微服務模型比單體模型的好處是顯而易見。所以如果是這樣的話 - 為什麼這種模式最近才流行?

如果這太好了,為什麼之前沒有這樣做呢?
這個問題有兩個答案。其中之一是,它正好是我們的技術能力應該做的,另一個是最近的技術進步,使我們能夠把它帶到一個新的水平。

當我開始寫這個問題的答案的時候,它變成了一個很長的描述,所以實際上我將把它分成另一篇文章,稍後再發表。在這個階段,我將跳過從單個程式到多個程式的過程,忽略ESB和麵向服務的體系結構,元件設計和有界的上下文等等概念。

有興趣的人可以分開閱讀更多關於發展過程的資訊。我們可以說在很多方面我們已經這樣做了一段時間,但是隨著最近容器技術(特別是Docker)和配合技術(如Kubernetes,Mesos,Consul等等)的普及,從技術的角度來看,這種模式變得更加可行。

所以,如果我們把它看作是我們可以實施微服務管理的話,我們就需要仔細考慮這個應該。我們已經看到了高層次的理論效益,但挑戰又如何呢?

微服務有什麼問題?
如果微服務是如此之偉大,那難道沒有大問題嗎?下面是我見過的一些最大的問題。

1. 開發人員的複雜性增加

對於開發者來說事情會變得更加困難。開發人員想要在合作的情況下,或者可能跨越許多服務的實現一個功能的情況下,開發人員必須在他們的機器上執行它們,或者連線到它們。這通常比簡單地執行單個程式更復雜。

這個挑戰可以透過工具得到部分緩解,但隨著構成系統的服務數量的增加,開發人員在整個系統執行時面臨的挑戰也越來越多。

(banq注:微服務實際是每個團隊負責自己的服務,跨服務開始實際就是跨團隊開發,微服務前提是組織架構決定技術架構,跨團隊實際是對組織架構的挑戰,當然會帶來複雜性,這個複雜性不是微服務本身帶來的。)

2.運營的複雜性增加

對於不開發微服務但卻維護微服務的團隊來說,潛在的複雜性是一個巨大的挑戰。他們不是管理幾個正在執行的服務,而是管理數十、數百或數千個正在執行的服務。存在有更多的服務,就需要更多的溝通途徑,以及更多潛在的失敗領域。

(banq注:避免單點失敗是實現多點,多點卻帶來複雜性,因此需要更強大的微服務運維監控平臺)

3.devops增加了複雜性

devops能夠減輕以上兩點嗎?

對於已經採用了devops的組織來說,這仍然很難。既是開發者又是運營者,已經非常艱難(要建立好的軟體卻很關鍵),但是也必須瞭解容器編排系統的細微差別,特別是掌握快速發展的系統是非常困難的。這使我想到下一點。

4.它需要嚴肅的專業知識

當由專家完成時,結果可能是美好的。但想象一下,如果一個單一的單體系統可能都不能順利執行的公司。怎麼可能在增加系統的數量,從而增加執行的複雜性以後能夠表現得更好呢?

是的,透過有效的自動化、監控和編排等,這一切都是可能的。但挑戰很少是技術 - 挑戰是找到能夠有效使用的人。目前這些技能需求非常高,可能很難找到。

5.現實世界的系統往往界限不清

在我們用來描述微服務的好處的所有例子中,我們談到了獨立的元件。但是在很多情況下,元件並不是獨立的。在論文中,某些領域可能看起來是有邊界界線,但是當你進入泥濘的細節時,你會發現他們比你預期的更具挑戰性。

這是事情變得非常複雜的地方。如果你的界限實際上是沒有明確定義,那麼會發生什麼情況是,即使理論上的服務可以單獨部署,你會發現,由於服務之間的相互依存關係,您必須部署一組服務。

這意味著您需要管理協同多個執行版本,這些版本的服務只有在合作執行才能透過驗證和測試,您實際上已經沒有可獨立部署的系統了,因為要部署新功能,您需要仔細編排許多服務以進行同時部署它們。

6.狀態的複雜性往往被忽略

在前面的例子中,我提到一個功能部署可能需要同時部署多個版本的許多服務。假設合理的部署技術可以緩解這種情況,例如藍/綠部署(大多數服務編排平臺很少費力地處理),或者並行執行多個服務版本的服務,以及決定使用哪個版本的消費通道。

如果服務是無狀態的,這些技術可以緩解大量的挑戰。但是無狀態的服務非常地容易處理。事實上,如果你有無狀態的服務,那麼我會傾向於考慮跳過微服務,並考慮直接使用無伺服器模型(serverless)。

實際上,許多服務需要狀態。前面影片共享平臺的一個例子可
能是訂閱服務。訂閱服務的新版本可以不同形式將資料儲存在訂閱資料庫中。如果您同時執行這服務的兩個版本,則等同於一次執行兩個模式的系統。如果您進行了藍綠色部署,而其他服務依賴於新形式中的資料,則必須同時更新這些資料,並且如果訂閱服務部署失敗並回滾,則可能還需要使用級聯回滾後果。

同樣,可能會想到,在NoSQL資料庫中,這些架構問題會消失,但事實並非如此。不強制執行資料結構化的資料庫不會消滅資料的結構化 - 它們只是意味著資料結構化往往應該是在應用程式級而不是資料庫級進行管理實現的的。理解資料的形式以及它們是如何演變等這些根本性問題挑戰是不能被消除。

7.通訊的複雜性往往被忽略

當你建立一個相互依賴的大型服務網路時,可能會有很多的服務間通訊。這導致了一些挑戰。首先,有很多事情可能會失敗。我們必須假設網路通訊是隨時可能失敗的,這意味著當一個服務呼叫另一個服務時,它應該至少需要重試幾次。如果當一個服務可能呼叫很多服務時,我們最終會遇到一個複雜的情況。

使用者上傳影片到一個影片共享服務中。我們可能還需要執行上傳服務,將資料傳遞到轉碼服務,更新推薦和訂閱狀態等等。所有這些呼叫都需要一定程度的協調,如果某個環節網路訊息失敗,我們則需要重試。

這個重試邏輯可能難以管理。試圖使用同步方式往往不會穩定,因為同步過程中的失敗點太多。在這種情況下,更可靠的解決方案是使用非同步模式來處理通訊。這裡面臨的挑戰是非同步模式固有地使系統具有了狀態性。如前所述,分散式狀態的系統很難處理。

當一個微服務系統使用訊息佇列進行服務內通訊時,你基本上有一個大的資料庫(訊息佇列或代理)將這些服務粘合在一起。同樣,雖然起初看起來似乎不是一個挑戰,但模式會回來咬你。X版本的服務可能會寫入某種格式的訊息,當訊息傳送者服務更改傳送訊息的細節時,依賴於該訊息的消費者服務也將需要隨著更新。

服務可以有處理許多不同格式訊息的能力,但這很難管理。假設,在部署新版本的服務時,您可能會有兩個不同版本的服務嘗試處理來自同一佇列的訊息,甚至可能是由不同版本的傳送服務傳送的訊息。這可能會導致複雜的邊緣情況。為了避免這些邊緣情況,僅允許特定版本的訊息存在可能更容易,這意味著您需要將一組服務的版本作為一個整體來部署,以確保先前版本的訊息被適當地排除,不會被處理。

這再次突出表明,獨立部署的想法當你進入細節時可能不會像預期的那樣簡單了。

8.版本控制可能很難

為了緩解前面提到的挑戰,版本控制需要非常謹慎的管理。再次,可以有一種趨勢,假設遵循像semver這樣的標準將解決這個問題。其實並不是。Semver是一個明智的使用慣例,但是您仍然需要跟蹤服務和可以一起工作的API的版本。

這可能會非常迅速地變得很具有挑戰性,並且可能會導致您不知道哪個版本的服務實際上可以一起正常工作。

在軟體系統中管理依賴關係是非常困難的,無論是節點Node模組,Java模組,C庫還是其他。獨立元件之間的衝突性的挑戰是很難被單一個產品處理的。

當依賴關係是靜態的時候,這些挑戰是處理起來比較棘手,但是還是可以進行修補,更新,編輯等,但是如果依賴關係本身是實時服務,那麼您可能無法更新它們 - 您可能需要執行許多版本(已經描述過這些挑戰),或者直到整個系統得到修復。

9.分散式事務

在需要跨操作事務完整性的情況下,微服務可能會非常痛苦。分散式狀態很難處理,很多小的單位可能會很難進行編排事務。

試圖透過使操作冪等性,提供重試機制等來避免這個問題可能是誘人的,在很多情況下這可能起作用,但是如果你只需要一個事務失敗或成功,而不需要處於中間狀態。解決這個問題或者在微服務模型中實現它的努力可能是非常高的。

10.微服務可能是變相的單體

是的,單獨的服務和元件可能是獨立部署的,但是在大多數情況下,您將不得不執行某種編排平臺,比如Kubernetes。如果您使用的是託管服務,例如Google的GKE 5或Amazon的EKS 6,則會為您處理管理群集的大量複雜性。

但是,如果您要自己管理叢集,那麼您正在管理一個龐大而複雜的關鍵任務系統。儘管單個服務可能具有前面所述的所有優點,但您需要非常小心地管理群集。這個系統的部署可能很難,更新可能很難,故障轉移可能很困難等等。

在許多情況下,總體收益仍然存在,但重要的是不要輕視或低估管理另一個龐大而複雜的系統的額外複雜性。託管服務可能會有所幫助,但在很多情況下,這些服務都是新興的(例如,Amazon EKS只是在2017年底才宣佈)。

微服務瘋狂之死!
透過仔細考慮的慎重決定能夠避免瘋狂。為了幫助解決這個問題,我已經注意到了一些你可能想問自己的問題,以及答案可能表明什麼:

1.隊伍大小:
你的團隊是圍繞一張大表嗎?
是,你也許不需要微服務,但是會有部署開發運維等挑戰性問題(比如因為修改一行程式碼導致整個專案重新部署等待很長時間)。
否,微服務也許能幫助你,當你有一個大型團隊或許多團隊時,元件之間的強邊界或隔離可能難以實現,透過將元件隔離進入服務也許會有幫助。


2.狀態:
你的系統大部分無狀態嗎?
是,可以考慮Serverless
否,微服務會帶來複雜性,不意味著不用微服務,但是注意隨著系統改變可能不是很容易管理。

3.消費者
你是為單一應用或服務構建一個解決方案嗎?
是,注意,如果你是為一個客戶構建系統,你發現你升級功能時,也許會一次性更新很多服務,微服務也許有效,但是設計領域時要非常小心。
否,如果你為很多不同客戶設計,微服務也許是一個方案,能夠快速為你的新客戶帶來新功能。

4.依賴性
你有很多服務依賴同一個實體嗎?
是,效能這時也許需要考慮,因為你存在單點效能風險,
否,微服務也許值得,如果你不依賴某個序列流,你也許能夠更加方便擴充套件服務,實現更有效的獨立。

5.專家
有容器編排devops專家嗎?
是,可以使用微服務。
否,devops容器編排的學習門檻比較高。

最後的想法:不要混淆微服務和架構
我故意在這篇文章中避免“a”字。但是,我的朋友佐爾坦(Zoltan)在驗證這篇文章的時候提到了一個很好的觀點。

其實並沒有微服務架構。微服務只是元件的另一種模式或實現,只不過是另一件事。無論是否存在於系統中,都不意味著系統的架構問題得到了解決。

微服務在許多方面與打包和運維的技術過程有關,而不是系統的固有設計。元件之間的邊界劃分仍然是工程系統中最重要的挑戰之一。

無論您的服務是否在Docker容器中,您總是需要仔細考慮如何將系統拼在一起。這裡沒有正確的答案,但有很多選擇。

The Death of Microservice Madness in 2018

相關文章