單體的優缺點前端
單體應用就是將應用程序的全部功能都打包成一個獨立的單元,最終以一個WAR包或JAR包存在,沒有外部的任何依賴,裏面包含DAO,Service、UI等全部的邏輯。單體應用有如下優勢:java
不幸的是,這種簡單的單元有很大的侷限性。應用程序隨着業務需求的迭代,功能的追加擴展,最終成爲一個龐然大物。變得更加複雜,邏輯耦合嚴重,難以理解,團隊開發 人員職責不清,部署困難,迴歸測試成本巨大,交付效率大大下降,總結下來,單體應用有一下缺點:redis
1. 複雜性高sql
代碼難以理解
在業務規模和團隊規模發展的必定階段,這些不足表現的更加明顯,單體架構的不足首先表如今複雜性上, maven模塊增多,多個模塊耦合在一塊兒,代碼結構混亂,使得團隊成員沒有一我的理解整個代碼邏輯;數據庫
難以理解致使代碼質量低,複雜性進一步增長
難以理解致使代碼複用度下降,由於你不知道哪些能夠複用的;即使修改,影響範圍也很差肯定,這致使這樣開發寧願新建一個新方法和新的類,進一步致使重複代碼越積越多;後端
2.交付效率低api
全量部署耗時長、影響範圍廣、風險大,發佈頻次低
正由於這種全量部署耗時長、影響範圍廣、風險大,致使咱們將不少功能和修復彙集在一塊兒進行開發完成,這致使了產品發佈頻次下降,新的功和更換的體驗能不能及時呈現給用戶,甚至被競爭對手趕超。
3.伸縮性(scalable)差瀏覽器
單體只能按總體橫向擴展,沒法分模塊垂直擴展安全
IO密集型模塊和CPU密集型模塊沒法獨立升級和擴容
業務模塊對資源的需求是不同的,因爲全部模塊部署到一塊兒,單體架構IO密集型模塊和CPU密集型模塊沒法獨立升級和擴容的,好比圖片壓縮,加解密這些 都是cpu資源密集的應該升級CPU,而IO密集型的模塊好比日誌收集服務IO操做比較多須要更大的內存,使用好比SSD性能更好的磁盤。
4. 可靠性差性能優化
一個bug有可能引發整個應用的崩潰
因爲全部模塊都是部署在一個實例中,一個bug會引發整個應用的崩潰,好比一個不重要的模塊的內存泄露就將會致使全部應用實例一個個crash掉
5.阻礙技術創新
那麼如何解決單體的不足呢,經過遷移到微服務架構來解決,咱們看一下什麼是微服務。
微服務的定義
微服務架構:將單體應用拆分爲多個高內聚低耦合的小型服務,每一個小服務運行在獨立進程,由不一樣的團隊開發和維護,服務間採用輕量級通訊機制,獨立自動部署,能夠採用不一樣的語言及存儲。
咱們經過上圖來看下單體架構到微服務架構的對比。此圖是一個簡單電商單體到微服務架構的演進圖,單體架構整個團隊維護開發一個大工程及一個單庫,到了微服務架構,用戶請求通過API Gateway被路由到下游服務,服務之間以輕量級通訊協議進行通訊,服務經過註冊中心發現彼此,每一個服務都有專門的開發維護團隊,每一個服務對應獨立的數據庫,服務獨立開發,獨立部署和上線。 接下來咱們總結下微服務的優勢。
微服務的優勢
易於開發與維護
微服務的挑戰
沒有任何技術是銀彈,微服務也是如此 ,都或多或少有一些缺點和問題。那麼咱們就必須針對這些問題一一解決,也是咱們接下來章節重點去作的. 我首先面對就是要將單體拆分紅多個服務。
1.服務拆分
微服務拆分原則:領域模型、限定上下文、組織架構、康威定律
現實中沒有一個具體明確的方法能夠將拆分一步到位,而是遵照必定的原則,好比根據領域模型、組織架構、單一職責這些進行拆分在拆分的過程當中還要結合經驗判斷,而且隨着需求迭代,架構持續優化演進,優化服務的拆分。
每一個微服務擁有獨立數據庫
服務拆分的同時還要考慮到存儲數據庫也要獨立,當多個服務直接讀寫數據庫中同一張表時,對這些表作任何改動都須要協調這些相關服務的部署。這一點違背了服務相互獨立這一原則。共享的數據存儲很容易不經意間形成耦合。每一個服務須要有本身的私有數據。好比訂單表被訂單服務和商品服務所共享,商品服務單獨作統計並不知道本身一天多少商品被賣出,不知道哪些數據由本服務產生的,就沒法進行技術產品規劃,對錶結構的修改也要通知多個服務,這是所不能容忍的。每一個服務須要本身的數據庫,但這些數據庫可共置在一臺共享的數據服務器上,數據庫私有的重點在於不該讓服務知道其餘服務底層數據庫的存在。可用一臺共享數據服務器先開始開發,之後若是數據量和併發量變大,服務器能夠進行隔離。服務器隔離後,只要更改配置便可將不一樣服務的數據庫隔離起來。
微服務之間肯定服務邊界,經過共享模型創建聯繫
每一個微服務都具有本身的業務能力,那麼服務之間交互的部分便是服務邊界; 肯定服務邊界也是一個難題,須要對本身的產品和業務有足夠的瞭解才能肯定最天然的服務邊界肯定服務邊界堅持的原則是要高內聚弱耦合,弱耦合就是一個服務與其餘服務的任何通訊都應經過公開暴露的接口(API、事件等)實現,這些接口須要妥善設計以隱藏內部細節。這樣咱們的服務之間保持獨立,在將來咱們能夠輕鬆重構,高內聚力就是密切相關的多個功能應儘可能包含在同一個服務中,這樣可將服務之間的干擾降至最低。
2.數據一致性
在單體架構中,咱們經過數據庫事務完成的操做 放在分佈式微服務架構下沒法完成了,由於實例被部署不一樣服務器上,好比訂單服務進行下單操做,下單操做和扣減庫存應該放在同一個事務中,在微服務架構下,下單操做和扣庫存操做被分佈在不一樣服務器上,就須要進行分佈式事務操做,而分佈式事務具備延遲較高、nosql數據庫不支持等缺點。這些缺點致使分佈式事務沒法應用到微服務中在微服務場景下,咱們一般使用最終一致性來代替強一致性。
3.服務通訊
4.服務網關
5.高可觀察
6.可靠性
在講單體的過程當中,咱們講到,一個業務模塊的內存泄露會致使整個進程退出。 在微服務場景下,若是一個服務出現內存泄露是不會影響 沒有依賴關係的服務的。 可是卻能夠由於該異常服務的僵死或不可用形成上游服務線程hang住,進而產生級聯效應,故障進一步向上游傳播。
提煉代碼腳手架
除了開發業務邏輯,咱們還須要搭建一套微服務工程可用框架,這樣是是爲了加快團隊工做效率,微服務解決方案保持統一,加強代碼複用性,統一進行優化,微服務要解決的問題很是多,因此抽取服務代碼模板是有必要的,它包括服務註冊發現、服務通訊、監控、日誌、異常處理等等。
從單體遷移到微服務
咱們先看這張圖,這張圖是從一篇外文中摘出來的,連接已經編輯在圖片中; 綠線表明單體架構,藍線表明微服務架構,X軸表明複雜度,Y軸表明生產效率。
當業務不復雜,團隊規模不大的時候,單塊架構比微服務架構具備更高的生產率(productivity),由於創建微服務架構須要額外的開銷來支持和管理微服務, 從而下降生產率;可是隨着業務複雜性的增長和團隊規模的擴大,單塊架構比微服務架構的生產率降低更趨明顯, 當複雜性達到一個臨界點,微服務架構的生產率會優於單塊架構, 由於微服務的鬆散耦合自治特性減緩了生產率的降低趨勢。
因此咱們在作項目時,必定要根據本身的團隊和業務複雜性來判斷,什麼時候應用微服務。 以個人經驗給你們的建議時,一個全新項目在1-3團隊時,能夠先拆分紅一個API 網關和一個集合全部業務的後端服務,API網關關注鑑權和路由、處理部分失敗;後端服務要劃分好業務模塊;項目初期,因爲流量很少,能夠沒必要添加流量控制和斷路器等組件。
同時即便向微服務架構遷移以後,拆分的粒度也要由粗到細演進式發展,必定要根據本身的業務規模複雜性和團隊規模來定。
一個策略是:不要大規模(big bang)重寫代碼(只有當你承擔重建一套全新基於微服務的應用時候能夠採用重寫這種方法)。重寫代碼聽起來很不錯,但實際上充滿了風險最終可能會失敗,就如Martin Fowler所說:「the only thing a Big Bang rewrite guarantees is a Big Bang!」
相反,應該採起逐步遷移單體式應用的策略,經過逐步生成微服務新應用,與舊的單體式應用集成,隨着時間推移,單體式應用在整個架構中比例逐漸降低直到消失或者成爲微服務架構一部分。這個策略有點像在高速路上限速到70邁對車作維護,儘管有挑戰,可是比起重寫的風險小不少。
Martin Fowler將這種現代化策略成爲絞殺應用,名字來源於雨林中的絞殺藤(strangler vine),也叫絞殺榕(strangler fig)。絞殺藤爲了爬到森林頂端都要纏繞着大叔生長,一段時間後,樹死了,留下樹形藤。這種應用也使用同一種模式,圍繞着傳統應用開發了新型微服務應用,傳統應用會漸漸退出舞臺。
SOA VS 微服務
SOA和微服務的對比是一個老生常談的話題,我認爲二者最大的不一樣是提出時所處的技術背景和環境。
SOA的出現實際上是爲了解決歷史問題:企業在信息化的過程當中會有各類各樣互相隔離的系統,須要有一種機制將他們整合起來,因此纔會有ESB的出現。一樣的,也成了SOA初期的服務是很大的概念,一般指定的一個能夠獨立運做的系統。
微服務沒有歷史包袱,服務的尺寸一般不會太大,從服務粒度來說,SOA更像是單體的簡單組合,而微服務是粒度更細小的服務,其次數據拆分SOA傾向於共享數據庫,微服務一個服務對應一個數據庫。
微服務知識全景圖
微服務知識全景圖會在課程《Java深刻微服務原理改造房產銷售平臺》中介紹和實踐。