微服務 (Microservices) 是一種軟件架構風格,將應用程序構造爲圍繞業務的小型自治服務的集合git
微服務以專一於單一責任與功能的小型功能區塊 (Small Building Blocks) 爲基礎。每一個服務都是獨立的,並實現單個業務功能github
微服務利用模塊化的方式組合出複雜的大型應用程序,各功能區塊使用與語言無關的 API 集相互通訊算法
微服務運用了以業務功能爲主導的設計概念,應用程序在設計時就能先以業務功能或流程設計先行分割,將各個業務功能都獨立實現成一個能自主運行的個體服務,而後再利用相同的協議將全部應用程序須要的服務都組合起來,造成一個應用程序數據庫
以購物車應用程序爲例,當打開購物車應用程序時,您看到的只是一個網站。可是,在後臺,購物車應用程序具備用於接受付款服務,客戶服務等設計模式
假設此應用程序的開發人員使用了單體框架,架構以下圖
服務器
如圖,在單體架構中,全部功能都放在一個代碼庫中,並在一個基礎數據庫下網絡
如今,假設市場上出現了一個新品牌,而且開發人員但願將即將到來的品牌的全部詳細信息放入此應用程序中架構
此時,不只須要處理新品牌的服務,並且還必須從新構建整個系統並相應地進行部署。爲了不此類挑戰,開發人員決定將其應用程序從單體架構轉換爲微服務app
開發人員爲搜索,推薦,客戶服務等建立了單獨的微服務負載均衡
此微服務架構不只能夠幫助開發人員克服之前的架構所面臨的全部挑戰,並且還能夠輕鬆地構建,部署和擴展購物車應用程序
以旅遊行業應用程序爲例
總體服務包括了旅客關係管理、付款、消息通知等服務
傳統的單體經常採用如上圖所示的總體式架構,並採起MVC的設計模式
三層架構(MVC)的具體內容以下
表示層(view): 用戶使用應用程序時,看到的、聽見的、輸入的或者交互的部分。
業務邏輯層(controller): 根據用戶輸入的信息,進行邏輯計算或者業務處理的部分。
數據訪問層(model): 關注有效地操做原始數據的部分,如將數據存儲到存儲介質(如數據庫、文件系統)及
從存儲介質中讀取數據等。
雖然如今程序被分紅了三層,但只是邏輯上的分層,並非物理上的分層。也就是說,對不一樣層的代碼而言,通過編譯、打包和部署後,全部的代碼最終仍是運行在同一個進程中
單體架構在規模比較小的狀況下工做狀況良好,可是隨着系統規模的擴大,它暴露出來的問題也愈來愈多,主要有如下幾點:
複雜性逐漸變高
好比有的項目有幾十萬行代碼,各個模塊之間區別比較模糊,邏輯比較混亂,代碼越多複雜性越高,越難解決遇到的問題
技術債務逐漸上升
公司的人員流動是再正常不過的事情,有的員工在離職以前,疏於代碼質量的自我管束,致使留下來不少坑,因爲單體項目代碼量龐大的驚人,留下的坑很難被發覺,這就給新來的員工帶來很大的煩惱,人員流動越大所留下的坑越多,也就是所謂的技術債務愈來愈多
維護成本大
當應用程序的功能愈來愈多、團隊愈來愈大時,溝通成本、管理成本顯著增長。當出現 bug 時,可能引發 bug 的緣由組合愈來愈多,致使分析、定位和修復的成本增長;而且在對全局功能缺少深度理解的狀況下,容易在修復bug 時引入新的 bug
持續交付週期長
構建和部署時間會隨着功能的增多而增長,任何細微的修改都會觸發部署流水線。新人培養週期長:新成員瞭解背景、熟悉業務和配置環境的時間愈來愈長
技術選型成本高
單塊架構傾向於採用統一的技術平臺或方案來解決全部問題,若是後續想引入新的技術或框架,成本和風險都很大
可擴展性差
隨着功能的增長,垂直擴展的成本將會愈來愈大;而對於水平擴展而言,由於全部代碼都運行在同一個進程,沒辦法作到針對應用程序的部分功能作獨立的擴展
將上面的總體架構改造爲如上圖所示的微服務
來自不一樣設備的不一樣客戶端嘗試使用不一樣的服務,例如搜索,構建,配置和其餘管理功能
全部服務均根據其功能進行分離,並進一步分離爲單個微服務
這些微服務具備本身的負載均衡和執行環境以執行其功能,並在其本身的數據庫中捕獲數據
微服務之間經過無狀態服務器(REST、GRPC或消息總線)進行通訊
微服務藉助服務發現來了解其通訊路徑並執行自動化,監控等操做功能
微服務執行的全部功能經過API網關傳達給客戶端
解耦
系統中的服務在很大程度上是解耦的。所以,整個應用程序能夠輕鬆構建,更改和擴展
組件化
微服務被視爲獨立的組件,能夠輕鬆替換和升級
專一業務功能
業務功能–微服務很是簡單,專一於單一功能
獨立自主
開發人員和團隊能夠彼此獨立地工做,從而提升了速度
持續交付
經過自動化的構建、測試和部署,容許頻繁發佈軟件
分散治理
重點是使用正確的工具完成正確的工做。這意味着沒有標準化模式或任何技術模式。開發人員能夠自由選擇最有用的工具來解決他們的問題
敏捷開發
微服務支持敏捷開發。任何新功能均可以快速開發並丟棄
單一職責
微服務架構中的每一個服務,都是具備業務邏輯的,符合高內聚、低耦合原則以及單一職責原則的單元,不一樣的服務經過「管道」的方式靈活組合,從而構建出龐大的系統
輕量級通訊
服務之間經過輕量級的通訊機制實現互通互聯,而所謂的輕量級,一般指語言無關、平臺無關的交互方式
對於輕量級通訊的格式而言,咱們熟悉的 XML 和 JSON,它們是語言無關、平臺無關的;對於通訊的協議而言,一般基於 HTTP,能讓服務間的通訊變得標準化、無狀態化。目前你們熟悉的 REST(Representational StateTransfer)、GRPC是實現服務間互相協做的輕量級通訊機制之一。使用輕量級通訊機制,可讓團隊選擇更適合的語言、工具或者平臺來開發服務自己
提升容錯性(fault isolation),一個服務的內存泄露並不會讓整個系統癱瘓
獨立性
服務獨立測試、部署、升級、發佈
在單塊架構中全部功能都在同一個代碼庫,功能的開發不具備獨立性;當不一樣小組完成多個功能後,須要通過集成和迴歸測試,測試過程也不具備獨立性;當測試完成後,應用被構建成一個包,若是某個功能存在 bug,將致使整個部署失敗或者回滾
新技術的應用,系統不會被長期限制在某個技術棧上
能夠根據市場需求,靈活多變的組合出新的業務場景
下降代碼耦合度
服務實例水平擴展,服務單一職責,功能獨立。保證可靠性與性能,提高資源利用
因爲微服務是以業務功能導向的實現,所以不會受到應用程序的干擾,微服務的管理員能夠視運算資源的須要來配置微服務到不一樣的運算資源內,或是布建新的運算資源並將它配置進去
提高開發交流,每一個服務足夠內聚,足夠小,代碼容易理解
進程隔離、故障隔離
單塊架構中,整個系統運行在同一個進程中,當應用進行部署時,必須停掉當前正在運行的應用,部署完成後再重啓進程,沒法作到獨立部署 有時候咱們會將重複的代碼抽取出來封裝成組件,在單塊架構中,組件一般的形態叫作共享庫(如 jar 包或者DLL),可是當程序運行時,全部組件最終也會被加載到同一進程中運行。
在微服務架構中,應用程序由多個服務組成,每一個服務都是高度自治的獨立業務實體,能夠運行在獨立的進程中,不一樣的服務能很是容易地部署到不一樣的主機上
即便應用程序的一項服務不起做用,系統仍然能夠繼續運行
數據分區,數據獨立,可靠性保證
微服務提升了系統的複雜度
開發人員要處理分佈式系統的複雜性
服務之間的分佈式事務問題
服務的註冊與發現問題
數據隔離再來的報表處理問題
不一樣服務實例的管理困難,持續自動化部署的要求
運維要求較高
對於單體架構來說,咱們只須要維護好這一個項目就能夠了,可是對於微服務架構來說,因爲項目是由多個微服務構成的,每一個模塊出現問題都會形成整個項目運行出現異常,想要知道是哪一個模塊形成的問題每每是不容易的,由於咱們沒法一步一步經過debug的方式來跟蹤,這就對運維人員提出了很高的要求
分佈式的複雜性
對於單體架構來說,咱們能夠不使用分佈式,可是對於微服務架構來講,分佈式幾乎是必會用的技術,因爲分佈式自己的複雜性,致使微服務架構也變得複雜起來
接口調整成本高
好比,用戶微服務是要被訂單微服務和電影微服務所調用的,一旦用戶微服務的接口發生大的變更,那麼全部依賴它的微服務都要作相應的調整,因爲微服務可能很是多,那麼調整接口所形成的成本將會明顯提升
微服務的規劃與單體式應用程序十分不一樣,微服務中每一個服務都須要避免與其餘服務有所牽連,且都要可以自主,並在其餘服務發生錯誤時不受干擾
假若真有溝通,也應採用異步溝通的方式來避免緊密的相依性問題。要達到此目的,則可用下列兩種方式:
事件存儲中心(Event Store)
這可讓你在服務集羣中廣播事件,而且在每一個服務中監聽這些事件並做處理,這令服務之間沒有緊密的相依性,而這些發生的事件都會被保存在事件存儲中內心。這意味着當微服務從新上線、部署時能夠重播(Replay)全部的事件。這也造就了微服務的數據庫隨時均可以被刪除、摧毀,且不須要從其餘服務中獲取數據
消息隊列(Message Queue)
可以在服務集羣中廣播消息,並傳遞到每一個服務中
比較有名的消息中間件如:NSQ、RabbitMQ、Nats、Kafka
A 服務上廣播一個事件,此事件能夠順帶一些數據。B 服務能夠監聽這個事件並在接收到以後有所處理。這些過程都是異步處理的
A 服務並不須要等到 B 服務處理完該事件後才能繼續,而這也表明 A 服務沒法獲取 B 服務的處理結果
與事件存儲中心不一樣的是:消息隊列並不會保存事件。一旦事件被消化(接收)後就會從隊列中消失
單個微服務在上線的時候,會向服務註冊中心註冊本身的 IP 位置、服務內容
當服務須要調用另外一個服務的時候,會去詢問服務探索中心該服務的 IP 位置,獲得位置後便可直接向目標服務發起調用
這麼作的用意是能夠統一集中全部服務的位置,就不會分散於每一個微服務中
服務發現中心能夠每隔一段時間就向微服務進行健康檢查(TCP 調用、HTTP 調用、Ping)
假若該服務在時間內沒有迴應,則將其從服務中心移除,避免其餘微服務對一個無迴應的服務進行調用
即使微服務從新在其餘ip上部署,其餘服務也是無感知的
比較經常使用的服務發現有:etcd,consul,廣泛都採用了raft等分佈式算法
網絡延遲
分佈式事務
限流
例如一個服務掛掉後,上游服務或者用戶通常會習慣性地重試訪問。這致使一旦服務恢復正常,極可能由於瞬間網絡流量過大又馬上掛掉
所以服務須要可以自我保護——限流。限流策略有不少,最簡單的好比當單位時間內請求數過多時,丟棄多餘的請求。另外,也能夠考慮分區限流。僅拒絕來自產生大量請求的服務的請求
熔斷
當一個服務由於各類緣由中止響應時,調用方一般會等待一段時間,而後超時或者收到錯誤返回
若是調用鏈路比較長,可能會致使請求堆積,整條鏈路佔用大量資源一直在等待下游響應。因此當屢次訪問一個服務失敗時,應熔斷,標記該服務已中止工做,直接返回錯誤。直至該服務恢復正常後再從新創建鏈接
服務降級
當Service A調用Service B,失敗屢次達到必定閥值,Service A不會再去調Service B,而會去執行本地的降級方法
降級服務其實就是犧牲掉一些邏輯處理,或者中止部分依賴服務的請求。以保障服務能夠提供關鍵能力
權限控制
API網關
分佈式追蹤
分佈式日誌記錄
配置中心