微服務的優缺點


本文來源於我在InfoQ中文站翻譯的文章,原文地址是:http://www.infoq.com/cn/news/2014/06/microservices


近期一段時間以來,社區中環繞着微服務產生了許多爭論,也充斥着大量的宣傳。過去的10年間,我們已經實現了許多笨重的SOA解決方式,微服務是業界期待已久的解決方式么?或者說微服務要比總體解決方式更加簡單?

在討論這些話題之前,我們最好先對微服務下個定義。在題為微服務的文章中,作者James LewisMartin Fowler是這樣定義微服務架構風格的:

開發單個應用作為一系列小型服務的套件,當中每一個服務都執行在自己的進程中,而且通過輕量級的機制實現彼此間的通信,這一般是HTTP資源API。這些服務是環繞着業務功能構建的,而且能夠通過全然自己主動化的部署機制進行獨立部署。這些服務的集中式管理做到了最小化,每一種服務都能夠通過不同的編程語言進行編寫,而且能夠使用不同的數據存儲技術。

微服務的一些優勢是顯而易見的:

  • 每一個服務都很easy,僅僅關注於一個業務功能。
  • 每一個微服務能夠由不同的團隊獨立開發。
  • 微服務是松散耦合的。
  • 微服務能夠通過不同的編程語言與工具進行開發。

這些優勢使得微服務看起來是很完美的解決方式,只是微服務難道就沒有缺點么?

Contino的CTO Benjamin Wootton正在基於微服務對一個系統進行架構設計,他遇到了不少困難,而且將遇到的這些問題發表在了題為Microservices - Not A Free Lunch!的文章中。以下是文章的一些摘要。

運維成本過高

故障恢復后,20個服務可能要占領40——60個進程,同一時候彈性問題也浮現出來了。在加入了負載均衡與消息中間件后,進程的數量還會持續添加。運維與編排全部這些服務是個“令人望而卻步的任務”,Wootton說到:

實現全部這些需求須要高質量的監控與運維基礎設施。保持一台應用server的持續執行就須要專人來負責,但如今我們還得確保幾十、甚至是幾百個進程都處於執行狀態、不能將磁盤空間耗盡、不能出現死鎖,還要保證性能。這真是一個很棘手的任務。

運維的過程須要自己主動化,只是由於“並沒有多少框架和開源工具能夠對此提供支持”,結果就是“使用微服務的團隊要在他們編寫具有業務價值的第一行代碼前須要大量使用自己定義腳本或是進行開發以管理這些進程”。

DevOps是必須的

Wootton覺得實現微服務的組織須要DevOps,這是由於:

你不能簡單地將通過這樣的風格構建的應用拋給運維團隊。開發團隊須要很關注運維與產品,由於基於微服務的應用與其環境上下文是很緊密地集成到了一起的。

由於許多服務可能都須要自己的數據存儲,因此開發人員還須要“搞清楚怎樣部署、執行、優化以及支持各種NoSQL產品”。

接口不匹配

服務依賴於彼此間的接口進行通信。改變一個服務的接口會對其它服務造成影響,Wootton談到:

改動了契約一方的語法或是語義,那么全部其它服務都須要理解這個改變。在微服務環境下,這意味着簡單的交叉改變會導致許多不同的組件發生變化,這些組件須要以一種協調一致的方式進行公布。

當然了,我們能夠通過向后兼容的方式避免這些變化的發生,只是實際情況卻是業務驅動的需求讓我們沒法實現分階段的公布。

假設彼此協同的服務向前推進而且不再同步了,比方說使用canary公布方式,那么改動消息格式的效果就難以可視化了。

代碼反復

為了避免將“同步耦合引入到系統中”,Wootton覺得有時須要向不同服務加入一些代碼,這就會導致代碼反復,而代碼反復“是很不好的,由於每一個代碼實例都須要進行測試和維護”。一種解決方式是在服務間使用共享庫,只是“在多語言環境下這即可不通了,而且引入了耦合就意味着服務須要並行公布來維護彼此間的隱式接口”。

分布式系統的復雜性

作為一種分布式系統,微服務引入了復雜性和其它若干問題,比方說“網絡延遲、容錯性、消息序列化、不可靠的網絡、異步、版本號化、應用層中的負載變化等等”。

異步

Wootton覺得微服務經常會使用異步編程、消息與並行,假設要求某個操作必須是同步且具有事務的,那么這就很復雜了,這要求我們得“管理好相關聯的ID以及分布式事務,將各種動作綁定在一起”。

測試

使用微服務架構時,測試是還有一個須要考慮的問題,由於“不管是手工測試還是自己主動化測試,我們都很難以一致的方式重現環境”,Wootton說到:

當加入了異步與動態消息負載后,要測試以這樣的風格構建的系統就難上加難了,同一時候也無法對將要公布到生產的各種服務抱有信心。

我們能夠測試每一個服務,只是在這樣的動態環境下,很微妙的行為都會從服務間的交互中產生出來,這是難以做到可視化的,也不易想清楚,更不必說全面的測試了。

Brady評論了Wootton的文章,談到了他嘗試從總體應用向微服務轉變的經歷:

正在從事的一個項目就在從一個總體應用向微服務遷移,我們遇到了你在文章中提到的大量問題。最后有大量反復代碼(由於這些服務是使用不同語言和框架構建的),遇到了許多“隱式契約”問題。比方說,將一個服務的User數據映射到還有一個服務上(當中一個服務不一定像還有一個服務一樣須要全部的數據)。盡管這樣的方式有一些顯而易見的優點,只是在使用之前一定要有很精心的規划才行。最后,我們所採取的方式是對總體應用進行模塊化(這樣就能夠在模塊間共享代碼倉庫、部署和代碼了,同一時候依舊保持良好的松散耦合的組件)並將一些模塊放到自己獨立的微服務中來實現獨立的部署與管理,當然了,我們僅僅在必要的情況下才這么做。

還有一位讀者Dennis Ehle也分享了他在微服務方面的經驗,他給出的結論是微服務是有代價的:

我們眼下為一個客戶實現了一個CD管道自己主動化框架,有450個開發人員,50個服務(或者叫微服務)。對於我來說,這樣的架構最迷人的地方在於這450個開發人員都不須要編寫一行代碼來支持顧客的用戶界面。UX方面的工作是由一個不同的小組完畢的。
盡管很靈活、風險小,而且節省了成本,這個客戶也很喜歡這一點,直接的結果就是從總體架構全然遷移過來了,只是毋庸置疑的是,由於文中提到的眾多因素,使用微服務還是須要付出額外的成本的。

此外,讀者Steve Willcox提到了微服務所引入的一些挑戰:

作為從總體Java應用轉換為SOA實現過程中的一名技術領導,我遇到了文中提到的全部問題,只是相對於將其看作是問題,我將他們看作構建更好的軟件的機會。

文中提到“須要大量的DevOps技術”,我覺得這很好啊。這樣,開發人員就有機會了解自己編寫的代碼是怎樣執行的了。採用SOA實現會迫使你成為一名DevOps,服務團隊開發人員自己做DevOps,而不像曾經那樣“將東西丟給集中化的運維團隊”。這對於讓開發團隊負責自己代碼的運維來說是積極的。

沒錯,相對於總體應用來說,採用微服務會有許多其它的服務要構建、測試和部署,只是時至今日,這些事情應該都是自己主動化的了。僅僅要遵循同樣的自己主動化模式,2個和20個的工作量事實上區別不大。

關於代碼反復,讀者Willcox覺得結果事實上沒那么差:

對於這一點,我過去是很純粹的,覺得全部的代碼反復都是不好的,只是接下來我認識到這樣的純粹性有時會導致更高的代價,更復雜的系統。我如今就變得很實際了,簡單性也是很重要的一個方面。我很認可Richard Gabriel在 The Rise of Worse is Better一文中對此的論述。

總而言之,微服務架構有許多吸引人的地方,只是在擁抱微服務之前,你須要認清它所帶來的挑戰。

查看英文原文:The Strengths and Weaknesses of Microservices


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM