最近閱讀了 Martin Fowler 和 James Lewis 合著的一篇文章 Microservices, 文中主要描述和探討了最近流行起來的一種服務架構模式——微服務,和我最近幾年工做的實踐比較相關感受深受啓發。本文吸取了部分原文觀點,結合自身實踐經驗來探討下服務架構模式的演化。前端
面向服務架構 SOA 思想概念的提出已不是什麼新鮮事,大概在10年前就有很多相關書籍介紹過。當時 Java 企業應用領域 J2EE 依然是主流,應用程序被部署在龐大統一的符合 J2EE 規範的容器中運行,在單一進程中提供全部的功能。 而 SOA 提出的一些架構原則,在當時看來無疑是革命性的。 因爲業已存在的大量單一龐大的應用,按照 SOA 的思想和架構原則來改造無疑至關於推翻從新開發一遍,在成本上很難接受。 所以早期的 SOA 一般和另一個術語關聯在一塊兒——ESB(企業服務總線)。 當時在 SOA 的實施思路上無一例外的選擇了 ESB 模式來整合集成大量單一龐大的應用,以保護企業前期投入成本。所以 ESB 實際上是 SOA 特定歷史階段的一種實現方式。web
然而,願望老是美好的,現實卻要殘酷的多。過去這些年咱們看到了不少實施 ESB 搞砸了的項目,投入幾百萬,產出幾乎爲 0,所以 SOA 這個概念也蒙上了不詳的標籤。 近幾年流行起來的服務化架構,其擁護者開始拒絕使用包裹着失敗陰影的 SOA 這個標籤,而稱其爲微服務架構(Microservices Architecture Style)。但事實上 微服務架構依然是 SOA 架構思想的一種實現。spring
對微服務架構咱們沒有一個明確的定義,但簡單來講微服務架構是:數據庫
採用一組服務的方式來構建一個應用,服務獨立部署在不一樣的進程中,不一樣服務經過一些輕量級交互機制來通訊,例如 RPC、HTTP 等,服務可獨立擴展伸縮,每一個服務定義了明確的邊界,不一樣的服務甚至能夠採用不一樣的編程語言來實現,由獨立的團隊來維護。
1. 經過服務實現組件化
傳統實現組件的方式是經過庫(library),傳統組件是和應用一塊兒運行在進程中,組件的局部變化意味着整個應用的從新部署。 經過服務來實現組件,意味着將應用拆散爲一系列的服務運行在不一樣的進程中,那麼單一服務的局部變化只需從新部署對應的服務進程。 另外將服務做爲組件能夠更明確的定義出組件的邊界,由於服務之間的調用是跨進程的,清晰的邊界和職責定義是設計時必須考慮的。編程
2. 按業務能力來劃分服務與組織團隊
康威定律(Conway's law)指出:後端
organizations which design systems ... are constrained to produce designs which are copies of the communication structures of these organizations.
任何設計系統的組織,最終產生的設計等同於組織以內、之間的溝通結構。
傳統開發方式中,咱們將工程師按技能專長分層爲前端層、中間層、數據層,前端對應的角色爲UI、頁面構建師等,中間層對應的角色爲服務端業務開發工程師,數據層對應着DBA等角色。 事實上傳統應用設計架構的分層結構正反應了不一樣角色的溝通結構。 而微服務架構的開發模式不一樣於傳統方式,它將應用按業務能力來劃分爲不一樣的服務,每一個服務都要求在對應業務領域的全棧(從前端到後端)軟件實現,從界面到數據存儲到外部溝通協做等等。 所以團隊的組織是跨功能的,包含實現業務所需的全面的技能。 近年興起的全棧工程師正是由於架構和開發模式的轉變而出現,固然具有全棧的工程師其實不多,但將不一樣領域的工程師組織爲一個全棧的團隊就容易的多。緩存
3. 服務即產品
傳統的應用開發都是基於項目模式的,開發團隊根據一堆功能列表開發出一個軟件應用並交付給客戶後,該軟件應用就進入維護模式,由另外一個維護團隊負責,開發團隊的職責結束。 而微服務架構的倡導者提議避免採用這種項目模式,更傾向於讓開發團隊負責整個產品的所有生命週期。Amazon 對此提出了一個觀點:服務器
You buidl it, you run it.
開發團隊對軟件在生產環境的運行負所有責任,讓服務的開發者與服務的使用者(客戶)造成天天的交流反饋,來自直接客戶端的反饋有助於開發者提高服務的質量。網絡
4. 智能終端與啞管道
微服務架構拋棄了 ESB 過分複雜的業務規則編排、消息路由等。 服務做爲智能終端,全部的業務智能邏輯在服務內部處理,而服務間的通訊儘量的輕量化,不添加任何額外的業務規則。架構
5. 去中心統一化
傳統應用中傾向採用統一的技術平臺或產品來解決全部問題。 不是每一個問題都是釘子,也不是每一個解決方案都是一個錘子。 問題有其具體性,解決方案也應有其針對性。 用最適合的技術方案去解決具體的問題,在大一統的傳統應用中其實很難作到,而微服務的架構意味着,你能夠針對不一樣的業務服務特徵選擇不一樣的技術平臺或產品,有針對性的解決具體的業務問題。
6. 基礎設施自動化
單一進程的傳統應用被拆分爲一系列的多進程服務後,意味着開發、調試、測試、集成、監控和發佈的複雜度都會相應增大。 必需要有合適的自動化基礎設施來支持微服務架構模式,不然開發、運維成本將大大增長。
7. Design for failure
正由於將服務獨立在不一樣的進程中後,引入了額外的失敗因素。 任什麼時候刻對服務的調用均可能由於服務方不可用致使失敗,這就要求服務的消費方須要優雅的處理此類錯誤。 這實際上是相對傳統應用開發方式的一個缺點,不過隨着一些開源服務化框架的出現,對業務開發人員而言適當的屏蔽了相似的錯誤處理,不過開發人員依然須要知道對服務的調用是徹底不一樣於進程內的方法或函數調用的。
8. 進化設計
一旦採用了微服務架構模式,那麼在服務須要變動時咱們要特別當心,服務提供者的變動可能引起服務消費者的兼容性破壞,時刻謹記保持服務契約(接口)的兼容性。 對於解耦服務消費方和服務提供方,伯斯塔爾法則(Postel's law)特別適用:
Be conservative in what you send, be liberal in what you accept.
發送時要保守,接收時要開放。
按照伯斯塔爾法則的思想來設計實現服務調用時,發送的數據要更保守,意味着最小化的傳送必要的信息,接收時更開放意味着要最大限度的容忍信息的兼容性。 多餘的信息不認識能夠忽略,而不該該拒絕或拋出錯誤。
採用微服務架構面臨的第一個問題就是如何將一個單一應用拆分爲多個服務。 有一個通常的原則是,單一服務提供的功能是能夠獨立被替換和升級的。 也就是說若是有 A 和 B 兩個功能,若是 A 功能發生變化時同時 B 功能也須要變化,那麼 A 和 B 這兩個功能應該被劃在一個服務中。
微服務架構應用的成功經驗近年已愈來愈多,例如國外的 Amazon,Netflix,國內如阿里都採用微服務架構取得了不少正面的成功案例。 但經過上文所述微服務架構特徵看出,其實微服務架構模式有利有弊,須要根據實際的業務、團隊、環境進行仔細權衡利弊。 其中的服務拆分帶來的額外開發、測試、運維、監控的複雜度,在現有的環境、團隊下是否可以很好的支持。
另外,有人可能會說,我一開始不採用微服務架構方式,而是在單一進程內基於清晰定義的模塊化方式,模塊之間經過接口調用,到了適當階段,必要的時候再將模塊拆分爲服務。 其實這個想法顯得過於理想,由於進程內良好定義的接口一般不是很好的服務化接口。 一開始沒有考慮服務化的設計方法,那麼後期拆分時依然是一個痛苦的過程。
優點與不足
微服務架構模式有不少好處。首先,經過分解巨大單體式應用爲多個服務方法解決了複雜性問題。在功能不變的狀況下,應用被分解爲多個可管理的分支或服務。每一個服務都有一個用RPC-或者消息驅動API定義清楚的邊界。微服務架構模式給採用單體式編碼方式很難實現的功能提供了模塊化的解決方案,由此,單個服務很容易開發、理解和維護。
第二,這種架構使得每一個服務均可以有專門開發團隊來開發。開發者能夠自由選擇開發技術,提供API服務。固然,許多公司試圖避免混亂,只提供某些技術選擇。而後,這種自由意味着開發者不須要被迫使用某項目開始時採用的過期技術,他們能夠選擇如今的技術。甚至於,由於服務都是相對簡單,即便用如今技術重寫之前代碼也不是很困難的事情。
第三,微服務架構模式是每一個微服務獨立的部署。開發者再也不須要協調其它服務部署對本服務的影響。這種改變能夠加快部署速度。UI團隊能夠採用AB測試,快速的部署變化。微服務架構模式使得持續化部署成爲可能。
最後,微服務架構模式使得每一個服務獨立擴展。你能夠根據每一個服務的規模來部署知足需求的規模。甚至於,你可使用更適合於服務資源需求的硬件。好比,你能夠在EC2 Compute Optimized instances上部署CPU敏感的服務,而在EC2 memory-optimized instances上部署內存數據庫。
Fred Brooks在30年前寫道,「there are no silver bullets」,像任何其它科技同樣,微服務架構也有不足。其中一個跟他的名字相似,『微服務』強調了服務大小,實際上,有一些開發者鼓吹創建稍微大一些的,10-100 LOC服務組。儘管小服務更樂於被採用,可是不要忘了這只是終端的選擇而不是最終的目的。微服務的目的是有效的拆分應用,實現敏捷開發和部署。
(1),微服務應用是分佈式系統,由此會帶來固有的複雜性。開發者須要在RPC或者消息傳遞之間選擇並完成進程間通信機制。更甚於,他們必須寫代碼來處理消息傳遞中速度過慢或者不可用等局部失效問題。固然這並非什麼難事,但相對於單體式應用中經過語言層級的方法或者進程調用,微服務下這種技術顯得更復雜一些。
(2)關於微服務的挑戰來自於分區的數據庫架構。商業交易中同時給多個業務分主體更新消息很廣泛。這種交易對於單體式應用來講很容易,由於只有一個數據庫。在微服務架構應用中,須要更新不一樣服務所使用的不一樣的數據庫。使用分佈式交易並不必定是好的選擇,不只僅是由於CAP理論,還由於今天高擴展性的NoSQL數據庫和消息傳遞中間件並不支持這一需求。最終你不得不使用一個最終一致性的方法,從而對開發者提出了更高的要求和挑戰。
(3)測試一個基於微服務架構的應用也是很複雜的任務。好比,採用流行的Spring Boot架構,對一個單體式web應用,測試它的REST API,是很容易的事情。反過來,一樣的服務測試須要啓動和它有關的全部服務(至少須要這些服務的stubs)。再重申一次,不能低估了採用微服務架構帶來的複雜性。
(4)其挑戰在於,微服務架構模式應用的改變將會波及多個服務。好比,假設你在完成一個案例,須要修改服務A、B、C,而A依賴B,B依賴C。在單體式應用中,你只須要改變相關模塊,整合變化,部署就行了。對比之下,微服務架構模式就須要考慮相關改變對不一樣服務的影響。好比,你須要更新服務C,而後是B,最後纔是A,幸運的是,許多改變通常隻影響一個服務,而須要協調多服務的改變不多。
(5)部署一個微服務應用也很複雜,一個分佈式應用只須要簡單在複雜均衡器後面部署各自的服務器就行了。每一個應用實例是須要配置諸如數據庫和消息中間件等基礎服務。相對比,一個微服務應用通常由大批服務構成。例如,根據Adrian Cockcroft,Hailo有160個不一樣服務構成,NetFlix有大約600個服務。每一個服務都有多個實例。這就形成許多須要配置、部署、擴展和監控的部分,除此以外,你還須要完成一個服務發現機制(後續文章中發表),以用來發現與它通信服務的地址(包括服務器地址和端口)。傳統的解決問題辦法不能用於解決這麼複雜的問題。接續而來,成功部署一個微服務應用須要開發者有足夠的控制部署方法,並高度自動化。
(6)一種自動化方法是使用PaaS服務,例如Cloud Foundry。PaaS給開發者提供一個部署和管理微服務的簡單方法,它把全部這些問題都打包內置解決了。同時,配置PaaS的系統和網絡專家能夠採用最佳實踐和策略來簡化這些問題。另一個自動部署微服務應用的方法是開發對於你來講最基礎的PaaS系統。一個典型的開始點是使用一個集羣化方案,好比配合Docker使用Mesos或者Kubernetes。後面的系列咱們會看看如何基於軟件部署方法例如NGINX,能夠方便的在微服務層面提供緩存、權限控制、API統計和監控。
總的說來,微服務有如下幾個特徵:1. 經過服務實現組件化;2. 按業務能力來劃分服務與組織團隊;3. 服務即產品;4. 智能終端與啞管道;5. 去中心統一化;6. 基礎設施自動化;7. Design for failure;8. 進化設計
能夠學習一下Spring Cloud 微服務架構集大成者,雲計算最佳業務實踐。:https://springcloud.cc/