本文來源於我在InfoQ中文站翻譯的文章,原文地址是:http://www.infoq.com/cn/news/2014/06/microserviceshtml
近期一段時間以來,社區中環繞着微服務產生了許多爭論,也充斥着大量的宣傳。過去的10年間,咱們已經實現了許多笨重的SOA解決方式,微服務是業界期待已久的解決方式麼?或者說微服務要比整體解決方式更加簡單?編程
在討論這些話題以前,咱們最好先對微服務下個定義。在題爲微服務的文章中,做者James Lewis與Martin Fowler是這樣定義微服務架構風格的: 網絡
開發單個應用做爲一系列小型服務的套件,當中每個服務都執行在本身的進程中,並且經過輕量級的機制實現彼此間的通訊,這通常是HTTP資源API。這些服務是環繞着業務功能構建的,並且可以經過全然本身主動化的部署機制進行獨立部署。這些服務的集中式管理作到了最小化,每一種服務都可以經過不一樣的編程語言進行編寫,並且可以使用不一樣的數據存儲技術。
微服務的一些優點是顯而易見的:架構
這些優點使得微服務看起來是很完美的解決方式,只是微服務難道就沒有缺點麼?負載均衡
Contino的CTO Benjamin Wootton正在基於微服務對一個系統進行架構設計,他遇到了很多困難,並且將遇到的這些問題發表在了題爲Microservices - Not A Free Lunch!的文章中。如下是文章的一些摘要。框架
運維成本太高運維
故障恢復後,20個服務可能要佔領40——60個進程,同一時候彈性問題也浮現出來了。在加入了負載均衡與消息中間件後,進程的數量還會持續添加。運維與編排所有這些服務是個「使人望而卻步的任務」,Wootton說到:異步
實現所有這些需求需要高質量的監控與運維基礎設施。保持一臺應用server的持續執行就需要專人來負責,但現在咱們還得確保幾10、甚至是幾百個進程都處於執行狀態、不能將磁盤空間耗盡、不能出現死鎖,還要保證性能。這真是一個很棘手的任務。
運維的過程需要本身主動化,只是因爲「並無多少框架和開源工具可以對此提供支持」,結果就是「使用微服務的團隊要在他們編寫具備業務價值的第一行代碼前需要大量使用本身定義腳本或是進行開發以管理這些進程」。編程語言
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一文中對此的論述。
總而言之,微服務架構有許多吸引人的地方,只是在擁抱微服務以前,你需要認清它所帶來的挑戰。