2018微服務狂熱之死
譯自dwmkerr "The Death of Microservice Madness in 2018"
微服務在過去幾年成為一個非常受歡迎的話題。
「微服務狂熱」就像這樣:
Netflix在devops上非常棒。 Netfix做微服務。 所以:如果我做微服務,我也就非常擅長devops了。
很多情況下,我們已經付出了巨大的努力來選用微服務模式,而沒有清楚應用於當前具體問題的成本和收益。
我將詳細描述微服務是什麼,為什麼這種模式非常吸引人,還有一些目前遇到的關鍵挑戰。
如果你正在考慮微服務是否適合你,我會用一系列簡單的問題來結束這個問題。 這些問題在文章的最後。
什麼是微服務,為什麼如此流行?
讓我們從基礎開始。 以下是一個假想的視頻共享平台的實現方式,首先是一個monolith(單個單元),然後是microservices微服務的形式:
兩個系統的區別在於第一種是單一模型, 宏系統。 第二種是一組小的,特定的服務集合。 每個服務都有特定的角色。
通過上述圖表展示,很容易看出,微服務有很多潛在的好處:
獨立開發:小型獨立組件可由小型獨立團隊構建。一個小組可以改變「Upload」服務,而不會干擾「Transcode」服務,甚至不知道這個服務。了解組件的時間大大減少,開發新功能也更加容易。
獨立部署:每個單獨的組件都可以獨立部署。這樣可以以更快的速度和更少的風險釋放新功能。比如對 「Streaming」組件的修復可以獨立部署,而不需要部署其他組件。
獨立伸縮:每個組件可以彼此獨立地進行伸縮。有新劇集時,服務負載加重,可以擴容「Download」組件,以處理增加的負載,而不必擴容其他組件,這使得彈性縮放更加可行,並且降低了成本。
可重用性:組件實現一個小的,特定的功能。這意味著它們可以更容易地適用於其他系統,服務或產品。 「Transcode」組件可以被其他業務部門使用,甚至可以變成一個新的業務,也許為其他組提供轉碼服務。
在這個層面上,微服務模型相對於單一模型的好處顯而易見。所以如果是這樣的話 - 為什麼這種模式最近才流行?
如果這麼好,為什麼之前沒有這樣做呢?
這個問題有兩個答案。其中之一是,盡技術所能,另一個是最近的技術進步使我們能夠把它提升到一個新的水平。
當我開始寫這個問題的答案的時候,微服務發展是個很長的過程,所以實際上我將把它分成另一篇文章,稍後再發表(請關注作者Twitter)。在這個階段,我將跳過從單個程序到多個程序的過程,忽略Enterprise service bus(企業服務匯流排)和Service Orientated Architecture(面向服務的體系結構),component design(組件設計)和BoundedContext(有界上下文,領域驅動設計概念)等等。
有興趣的人可以分開閱讀更多關於整個微服務演進的資料。相反,我會說在很多方面我們已經這樣做了一段時間了,但是隨著最近容器技術(特別是Docker)和orchestration technology(服務編排技術)(如Kubernetes,Mesos,Consul等等)的普及,從技術的角度來看,這種模式變得更加可行。
所以,如果我們把它看作是我們可以實施微服務安排的話,我們就需要仔細考慮這個應該。我們已經從整體看到了效益,但又有哪些挑戰呢?
微服務有哪些問題?
微服務即使如此的好,那又什麼大不了的?下面是思考的一些比較大的問題。
增加開發的複雜性
對於開發者來說事情會變得更加困難。在開發人員想要在旅程中工作的情況下,或者可能跨越許多服務的功能的情況下,開發人員必須在他們的機器上運行這些服務,或者連接到這些服務。這通常比簡單地運行單個程序更複雜。
這個挑戰可以通過工具(docker)得到部分緩解,但隨著構成系統的服務數量的增加,開發人員在整個系統運行時面臨的挑戰也越來越多。
增加運維的複雜性
對於不開發服務但維護服務的團隊來說,潛在的複雜性是一個巨大的挑戰。他們不是管理幾個正在運行的服務,而是管理數十,數百或數千個正在運行的服務。有更多的服務,更多的溝通途徑,以及更多潛在的失敗領域。
增加devops的複雜性
閱讀以上兩點,可能會感到運維和開發是分開處理的,尤其是考慮到devops作為一種實踐的普及(我是一個很大的支持者)。不開發緩解這一點?
面臨的挑戰是,多團隊仍然依靠獨立的開發和運維團隊來運行 , 相比來說單一團隊則更傾向於採用微服務。
對於已經採用了devops的團隊來說,這仍然很難。既是開發者又是運維,已經非常艱難(但是要建立好的軟體卻很關鍵),但是也必須了解編排系統的細微差別,特別是快速發展的系統是非常困難的。這使我想到下一點。
它需要更多的專業知識
當由專家完成時,結果可能是美好的。但想像一下,一個獨立團隊如果連monolithic(單一系統)系統都不能平滑設計和維護。又怎麼能增加系統數量,從而增加運行的複雜性呢?
是的,通過有效的自動化,監控和編排等,這一切都是可能的。但挑戰很少是技術,卻是找到能夠有效使用這些技術的人。目前這些技能需求非常高,可能很難找到。
現實世界的業務往往界限不清
在我們用來描述微服務的好處的所有例子中,我們談到了獨立的組件。但是在很多情況下,組件並不是獨立的。在論文中,某些領域可能看起來有限,但是當你進入泥濘的細節時,你會發現他們比你預期的更具挑戰性。
這是事情變得非常複雜的地方。如果你的邊界實際上沒有被很好地定義,那麼會發生什麼,即使理論上可以孤立地部署服務,你會發現由於服務之間的相互依賴關係,你必須將服務獨立組合部署。
這意味著您需要管理協同版本,這些版本的服務在合作時經過驗證和測試,您實際上沒有可獨立部署的系統,因為要部署新功能,您需要仔細編排許多依賴服務,並且同時部署。
服務狀態的複雜性往往被忽略
在前面的例子中,我提到一個功能部署可能需要同時部署多個版本的許多服務。假設合理的部署技術將緩解這種情況,例如blue/green(藍/綠部署)(大多數服務編排平台都能做到),或者並行運行多個服務版本的服務,以及決定使用哪個版本。
如果服務是無狀態的,這些技術可以減輕很多挑戰。但是無狀態的服務非常簡潔,容易處理。事實上,如果你有無狀態的服務,那麼我會傾向於考慮跳過微服務,並考慮使用serverless(無伺服器模型)。
實際上,許多服務需要狀態。我們還是用視頻共享平台這個中,訂閱服務。訂閱服務的新版本可以以不同形狀將數據存儲在訂閱資料庫中。如果您同時運行這兩個服務,則一次運行兩個系統。如果您進行了藍綠色部署,而其他服務依賴於新系統中的數據,則必須同時更新這些數據,並且如果訂閱服務部署失敗並回滾,則可能還需要回滾,考慮級聯後果。
同樣,可能會想到,在NoSQL資料庫中,這些架構問題會消失,但事實並非如此。 不強制執行scheme的資料庫不會導致無scheme系統,相反它們只是意味著scheme往往是在應用程序級而不是用資料庫級進行管理的。 理解數的模型以及如何抽象這些根本性挑戰不能被消除。
溝通的複雜性往往被忽略
當你建立一個相互依賴的大型服務網路時,可能會有很多的服務間通信。這導致了一些挑戰。首先,有很多事情可能會失敗。我們必須期望網路通信有可能失敗,這意味著當一個服務請求另一個服務時,它應該至少需要重試幾次。現在當一個服務可能調用很多服務時,我們最終會遇到一個複雜的情況。
用戶通過「video sharing」服務進行上傳視頻。我們可能需要運行「upload service」上傳服務,將數據傳遞到「transcode service」轉碼服務,更新subscriptions訂閱,更新recommendations建議等等。所有這些請求都需要一定程度的處理,如果請求失敗,我們需要重試。
這個重試邏輯可能難以管理。試圖同步做事往往會導致站不住腳,失敗點太多。在這種情況下,更可靠的解決方案是使用非同步模式來處理請求。這裡面臨的挑戰是非同步模式(固有地使系統具有狀態性)。如前所述,分散式系統狀態很難處理。
當一個微服務系統使用消息隊列進行服務內通信時,你基本上有一個大的資料庫(消息隊列或broker代理)將這些服務粘合在一起。同樣,雖然起初看起來似乎不是一個挑戰,版本迭代,契約變更會很痛。 V1版本的服務可能會發送某種格式的消息,當發送服務更改其發送的消息的契約時,依賴於此消息的服務也將需要更新(>排除向下兼容模式)。
你可以說,這可以有許多不同格式的消息處理的服務,但這很難管理。現在,在部署新版本服務時,您可能會有兩次不同版本的服務嘗試處理來自同一隊列的消息,甚至可能是由不同版本的發送服務發送的消息。這可能會導致複雜的邊界情況。為了避免這些邊界情況,僅允許特定版本的消息存在可能更容易,這意味著您需要將一個服務的一個版本作為一個整體服務來部署,以確保先前版本的消息得到適當的處理。
這再次強調,獨立部署的想法可能不會像預期的那樣。
版本控制可能很難
為了緩解前面提到的挑戰,版本控制需要非常謹慎的管理。一種趨勢,假設遵循像Semver Semantic Versioning(語義化版本)這樣的標準將解決這個問題。 Semver是一個明智的使用習慣,但是仍然需要跟蹤依賴的API版本才能正常工作。
這可能會變得非常具有挑戰性,並且可能會導致你不知道哪個版本的服務實際上可以一起正常工作。
在軟體系統中管理依賴關係是非常困難的,無論是node模塊,Java模塊,C庫還是其他。當一個實體消費獨立模塊之間的衝突的挑戰是很難被處理的。
當依賴關係是靜態的時候,這些挑戰就已經很難,但可以通過patched打修補,更新,編輯等進行處理。如果依賴關係本身是在線系統,那麼可能無法更新它們 ,這就可能需要運行許多版本(已經描述過這些挑戰),或者直到整個系統得到修復。
分散式事務
在需要跨transaction(事務)操作完整性的情況下,微服務可能會非常痛苦。分散式狀態很難處理,很多小的單位可能會很難進行編排事務。
試圖通過使操作冪等性,提供重試機制等來避免這個問題可能是誘人的,並且在很多情況下這可能起作用。但是你可能有一些情況,你只需要一個事務失敗或成功,而不會處於中間狀態。解決這個問題或者在微服務模型中實現它的成本是非常高的。
微服務可能是變相的monoliths服務
是的,不同服務和組件可能是獨立部署的,但是在大多數情況下,您將不得不運行某種編排平台,比如Kubernetes。如果使用的是託管服務,例如Google的GKE(Google Cloud Platform for Kubernetes)或Amazon的EKS(Amazon Elastic Container Services for Kubernetes),則會為您處理管理群集的大量複雜性。
但是,如果您要自己管理集群,那麼您正在管理一個龐大而複雜的關鍵任務系統。儘管單個服務可能具有前面所述的所有優點,但您需要非常小心地管理群集。這個系統的部署可能很難,更新可能很難,故障轉移可能很困難等等。
在許多情況下,總體收益仍然存在,但重要的是不要輕視或低估管理另一個龐大而複雜的系統的額外複雜性。託管服務可能會有所幫助,但在很多情況下,這些服務都是新興的(例如,Amazon EKS只是在2017年底才宣布)。
微服務狂熱之死!
通過仔細考慮決定避免狂熱。 為了幫助解決這個問題,我已經注意到了一些你可能想問自己的問題,以及可能的答案:
問題整體PDF:
https://github.com/dwmkerr/blog/raw/master/2018/microservice-madness/images/microservice-questions.pdf
最後的想法:不要混淆微服務和架構
我故意避免這篇文章中提及架構兩字。但是,我的朋友佐爾坦(Zoltan)在證明這篇文章的時候提出了一個很好的觀點(他貢獻了這篇文章)。
沒有微服務體系架構。微服務只是組件的另一種模式或實現,不過如此罷了。無論是否存在於系統中,都不意味著系統的體系結構得到了解決。
微服務在許多方面與包裝和操作的技術過程有關,而不是系統的固有設計。部件的適當邊界仍然是工程系統中最重要的挑戰之一。
無論您的服務是否在Docker容器中,您總是需要仔細考慮如何將系統放在一起。在如此多的選擇中,沒有正確的答案。
我希望你發現這篇文章有趣!
Appendix: Further Reading
The following links might be of interest:
- Martin Fowler - Bounded Context - Martins articles are great, Id thoroughly recommend this.
- Martin Fowler - Microservices - An often recommended introduction to the pattern.
- Microservices - Good or Bad? - Bj?rn Frantzéns thoughts on microservices, after reading this article.
- When Not To Do Microservices - Excellent post on the topic from Christian Posta
- Dave Kerr - Microservices to Monoliths - Practical tips for CI/CD and DevOps in the Microservice world - A recent conference presentation I did on devops with microservices.
References
- https://trends.google.com/trends/explore?date=today%205-y&q=microservice ?
- If you dont want to miss the article, you can subscribe to the RSS Feed, or follow me on LinkedIn or Twitter. ?
- Docker Compose is a good solution, Fuge is very clever, and there is also the option of running orchestration locally as is the case with something like MiniKube. ?
- https://semver.org/ ?
- Google Kubernetes Engine, a managed service from Google Cloud Platform for Kubernetes: https://cloud.google.com/kubernetes-engine/?
- Amazon Elastic Container Services for Kubernetes, a managed service from Amazon Web Services for Kubernetes: https://aws.amazon.com/eks/ ?
推薦閱讀:
※鋼鐵俠3裡面的賈維斯系統是個什麼構造的?
※分散式一致性演算法:Raft 演算法(Raft 論文翻譯)
※Stellar深入淺出(1):Stellar簡介
※「分散式」「集群」「雲計算」三者是什麼區別呢?
※拜占庭將軍問題確保系統正常為什麼需要2k+1個正常節點?