Java生鮮電商平台-微服務架構概述
單體架構存在的問題
在傳統的軟件技術架構系統中,基本上將業務功能集中在單一應用內,或者是單一進程中。盡管現代化的軟件架構理論以及設計原則已推廣多年,但實際技術衍化的速度遲緩並且變革動力不足。 其中的原因存在着復雜性以及多樣性,我想主要的原因是沒有一套整體的解決方案能夠讓工程師在面臨穩定性風險下,毅然決然地實施系統重構。當系統應用規模隨着業務的迅速發展時,系統的重要性愈發突出,開發人員將對系統的改造尤為敏感,從之前的徘徊猶豫,隨之變得更加保守,只能延續過去的技術方案,將功能不斷地累積在原有的系統架構上。這樣的系統好比是豆腐疊羅漢,疊得越高越危險。因此,當面臨巨大的服務壓力時,系統不得不通過擴容的方式,來支撐應對。俗話說,“船小好調頭”,“頭病醫頭,腳病醫腳”。臃腫的系統使得擴容變得毫無針對性,牽一發而動全身。由於服務運行情況存在差異性,具體哪個功能存在性能瓶頸,又因服務並非孤立而存在,使得評估結果存在着主觀臆斷性和不確定性,這種相互影響和作用下,使得擴容變得異常的困難,擴容無法量化,最終導致“水桶效應”。
當應用場景規模增大時,為了提高了開發以及執行的效率,並且使得更優雅或者合適的解決問題成為可能,開發人員將會評估和選擇更先進的技術,推動演進。由於系統應用過分地集中了所有功能,其功能所需依賴服務以及執行庫文件也隨之變得龐大,當需要適配新的技術時,不僅依賴沖突難存在不確定性並且難以應付,進而使代碼重構變得異常困難,增加了適配新技術的難度。
正因為功能集中於一身,讓應用資源占用率變得越來越大,使得持續集成、回歸測試、以及分發部署變得愈發困難。比如,應用部署包磁盤占變多,讓編譯、打包、分發以及啟動時間變長,不確定性因素變得更大。當應用發布上線后,存在功能性缺陷,需要回滾時,這樣的試錯和時間成本變得更加昂貴。
越是功能集中式的系統架構,在開發工程中,越依賴於與執行環境。這種執行環境承載着數據、服務以及配置,如若其中那個環節出現問題,開發進程不得不被迫中斷,而不斷地診斷問題和調試環境,使得快速開發變得要不可及,更不要說在本地開發。由於對環境的過分依賴,使得系統的穩定性變得更不確定性。其一,由於服務相互依賴,而服務又依賴環境,開發人員對單元測試職業習慣以及依賴程度降低,使得測試環節減少,或者說更依賴於集成測試。其二,當測試人員在部署測試環境執行集成測試時,不但部署成功率不斷地降低,而且執行過程時間不斷地增加,壓縮了開發時間,也可能導致項目滯后。不僅提高了系統風險,並且增加了心理負擔。這么說來,無論是快速開發和測試都變得更加艱難。
以上分析還只是停留在那些熟悉業務和技術的成員,當業務快速發展時,其發展速度與開發效率比不斷擴大,招募和發展新人是必不可少的手段。當面對如此巨大和復雜的系統應用時,業務和技術所需的知識變得特別雜糅,讓新人有一種“獨上高樓望,盡天涯路”之感,學習曲線陡峭。在實際的實施過程中,文檔完整性以及指導的系統性皆存在不足。
如何解決單體架構存在的問題
單體應用給我們帶來的現實問題:
- 擴容困難(Problems in scalability )
- 部署困難(Problems in deployment)
- 發布回滾困難(Problems in release rollback)
- 適配新技術困難( Problems in adopting new technologies )
- 快速開發困難(Problems in RAD)
- 測試困難(Problems in testing)
- 學習困難(Problems in learning)
實際上,在解決單體應用的問題上,數年前,就出現了相應的解決方法,比如SOA的技術路線。
SOA解決一個現實的問題,那就是服務與服務之間解耦,將古老的進程內服務調用,通過網絡協議轉化成服務之間的調用。從早期發明了CORBA、RMI、COM+、XML-PPC等技術,不過問題也隨之出現,由於這些技術綁定在某種技術或者平台,比如RMI屬於Java 平台技術,COM+屬於微軟技術體系,XML=PRC沒有統一的協議標准,因此對平台無關性的通訊需要的協議呼聲強烈,這時一些典型的技術陸續出現,如WebServices以及MessageQueue。以及它們的集大成技術ESB。
其中的代表技術有:WSDL(Web Service Definition Language)、SOAP(Simple Object Access Prototol)等技術。由於這些通訊協議標准相對笨重,雖然目前仍在被廣泛的使用,但逐步被淘汰是大勢所趨。
為什么不選SOA而選微服務
面向服務架構(SOA) VS 微服務
類同
- 面向服務( Service-Oriented )
- 松耦合(Loose-Coupling)
- 自包含(Self-Contained)
- 平台無關性(Independent Platform)
差異
- 原子性(Atomic)
- 自治性(Autonomous)
- 開發運維體系(DevOps)
- 輕量級(Lightweight)
- 通訊協議(Communication Protocol)
微服務是粒度小的SOA,正由於SOA體系龐大,不可能實現更好的原子性,並且它采用了統一統治的方式,例如ESB那樣的大型解決方案。這樣技術選型,針對單一的服務無法實現自行管理,無形之中增加了團隊運維成本。開發人員不能很好的實施DevOps技術手段。同時,SOA采用了WSDL、SOAP等重量級的通訊協議,增加了開發成本以及性能損耗。在微服務中,大多數服務API通過REST的方式暴露,這樣大大地降低了適配的成本。
微服務是趨勢
讓我們看看google和百度統計的結果吧

圖(1)Google中spring boot的搜索熱度
spring boot和spring cloud是做微服務的最佳搭檔。從圖(1)上,我們能夠看到spring boot 2013年在全球開始流行,一直到2017年2月到了100的熱度。

圖(2)google中spring cloud的搜索熱度
從圖(2)上,我們可以看到spring cloud從2012年開始熱度都是比較平和,在2015年6月之后,也就是微服務開始興起的時候,spring cloud開始迅速增長,在2017年2月達到了100的搜索熱度。(地圖上沒有中國,估計是因為中國被牆掉了的原因)

圖(3)百度搜索中spring boot的搜索熱度
圖(3)是百度地圖統計的結果,我們可以看到spring boot在國內是2015年6月開始流行的,2017年增長尤為突出。

圖(4)百度搜索中spring cloud的搜索熱度
圖(4)我們可以看到,spring cloud是從2016年6月開始在中國流行,往往新技術要在中國流行,都會落后硅谷一年,看看一年前的硅谷,就是現在的中國,所以大家也就能夠判斷到了spring cloud在中國的發展曲線了,也就是2018年2月spring cloud在中國的熱度將達到頂峰。
雖然流行並不代表你需要。但是,既然流行就有他流行的原因,就有他優點。后面我們將回來認識下微服務。
什么是微服務
微服務是用一組小服務的方式來構建一個應用,服務獨立運行在不同的進程中,服務之間通過輕量的通訊機制(如RESTful接口)來交互,並且服務可以通過自動化部署方式獨立部署。正因為微服務架構中,服務之間是相互獨立的,所以不同的服務可以使用不同的語言來開發,或者根據業務的需求使用不同類型的數據庫。
微服務架構的優點與挑戰
優勢
-
服務簡單,只關注一個業務功能
傳統的整體風格的架構在構建部署和擴展伸縮方面有很大的局限性,其服務端應用就像是一塊鐵板,笨重且不可拆分,系統中任何程序的改變都需要整個應用重新構建和部署新版本。在進行水平擴展時也只能整個系統擴展,而不能針對某一個功能模塊進行擴展。 而微服務架構將系統以組件化的方式分解為多個服務,服務之間相對獨立且松耦合,單一功能的改變只需要重新構建部署相應的服務即可。 -
每個微服務可由不同團隊開發
傳統的開發模式在分工時往往以技術為單位,比如UI團隊、服務端團隊和數據庫團隊,這樣的分工可能會導致任何功能上的改變都需要跨團隊溝通和協調。而微服務則倡導圍繞服務來分工,不同的服務可以采用不同的技術來實現,一個團隊中應該包含開發所需的所有技能,比如用戶體驗、數據庫、項目管理。 -
微服務是松散耦合的
微服務架構拋棄了ESB復雜的業務規則編排、消息路由等功能,微服務架構中服務是高內聚的,每個服務都會處理相應的業務,所有的業務邏輯應該盡量在服務內部處理,且服務間的通信盡可能的輕量化,比如使用Restful的方式。 -
可用不同的編程語言與工具開發
傳統的軟件開發中經常會使用同一個技術平台來解決所有的問題,而經驗表明使用合適的工具做合適的事情會讓開發變得事半功倍。微服務架構天生就具有這樣的特性,我們可以使用Node.js來開發一個簡單的報表頁面,使用C++來編寫一個實時聊天組件。
挑戰
-
運維開銷
更多的服務也就意味着更多的運維,產品團隊需要保證所有的相關服務都有完善的監控等基礎設施,傳統的架構開發者只需要保證一個應用正常運行,而現在卻需要保證幾十甚至上百道工序高效運轉,這是一個艱巨的任務。 -
DevOps要求
使用微服務架構后,開發團隊需要保證一個Tomcat集群可用,保證一個數據庫可用,這就意味着團隊需要高品質的DevOps和自動化技術。而現在,這樣的全棧式人才很少。 -
隱式接口
服務和服務之間通過接口來“聯系”,當某一個服務更改接口格式時,可能涉及到此接口的所有服務都需要做調整。 -
重復勞動
在很多服務中可能都會使用到同一個功能,而這一功能點沒有足夠大到提供一個服務的程度,這個時候可能不同的服務團隊都會單獨開發這一功能,重復的業務邏輯,這違背了良好的軟件工程中的很多原則。 -
分布式系統的復雜性
微服務通過REST API或消息來將不同的服務聯系起來,這在之前可能只是一個簡單的遠程過程調用。分布式系統也就意味着開發者需要考慮網絡延遲、容錯、消息序列化、不可靠的網絡、異步、版本控制、負載等,而面對如此多的微服務都需要分布式時,整個產品需要有一整套完整的機制來保證各個服務可以正常運轉。 -
事務、異步、測試面臨挑戰
跨進程之間的事務、大量的異步處理、多個微服務之間的整體測試都需要有一整套的解決方案,而現在看起來,這些技術並沒有成熟。
微服務設計原則
-
隔離
服務必須設計為單獨相互隔離工作。當你將一個整體單片系統分解成一組服務時,這些服務必須彼此解耦,這樣才能更加連貫和自給自足。每個服務應該能夠處理其自己的故障,而不會影響或破壞整個應用程序或系統。隔離和解耦特性使服務能夠非常快速地從故障狀態中恢復。服務的隔離特性具有以下優點:容易采用連續交付,更好的擴展,有效的監控和可測試性。 -
自治性
隔離為自治性鋪平了道路。 服務必須設計為自主自治的。它必須具有凝聚力,能夠獨立地實現其職能。每個服務可以使用良好定義的API(URI)獨立調用。API以某種方式標識服務功能。自主服務還必須處理自己的數據。更流行的術語是多語言持久性,其中每個服務都有自己的持久存儲。 自主還確保彈性。自主服務具有以下優點:有效的服務編排和協調,更好的擴展,通過良好定義的API進行通信,更快速和可控的部署。 -
單一責任
服務必須設計為高度凝聚。單一的職責(責任)原則是服務只執行一個重要的功能。 單一責任與“微觀”一詞很好地結合。‘微’意味着小,細粒度,只與其責任范圍內相關。單一責任功能具有以下優點:服務組合無縫,更好的擴展,可重用性,可擴展性和可維護性。 -
有界上下文
您的服務應該有多大或小? 答案就在於所謂有界上下文設計原則。這是一個關鍵模式,同時是領域驅動設計(DDD)建模方法。有界的上下文是關於微服務將提供其服務功能的上下文。它根據有關領域模型和識別離散邊界,並相應地設計您的微服務,使其更具凝聚力和自主性。這也意味着跨邊界的通信變得更有效率,在一個有界上下文中的服務不需要依賴於另外一個有限上下文中的太多的事情了。 -
異步通信
在設計離散邊界和使用其自己的有界上下文設計服務時,跨邊界的服務通信必須是異步的。異步通信模式自然導致服務之間的松耦合,並允許更好的縮放。使用同步通信,會阻止調用並等待響應。 處於阻塞狀態的服務不能執行另一個任務,直到接收到響應並釋放底層線程為止。它導致網絡擁塞,並影響延遲和吞吐量。異步通信還可以帶來實現良好定義的集成或通信模式的概念,以實現涉及不同服務的邏輯工作流。 -
位置獨立
根據設計,微服務是在虛擬化環境或docker容器中部署。隨着雲計算的出現,我們可以擁有大量可以利用動態縮放環境的服務實例。服務可以在跨小型或大型集群的多個節點上運行。服務本身可以根據底層計算資源的可用性或效率來重新定位。必須能夠以位置獨立的方式來尋址或定位服務。通常,可以使用不同的查找發現模式來消費使用您的服務。服務的客戶端或消費者不必煩惱部署或配置特定服務的位置。它只是使用某種邏輯或虛擬地址來定位服務。