微服務目前是軟件開發的一種新趨勢,咱們所熟知的谷歌、亞馬遜,Netflix等都在使用微服務架構。 但微服務架構與總體架構的區別在哪?微服務架構又須要注意哪些運營成本?數人云今天給你們帶來的文章將闡述這幾個問題。數據庫
本文咱們將討論微服務架構與總體架構的區別,爲了清晰起見,本文假設:在此上下文中微服務的定義是須要服務之間的物理分離。編程
微服務加固被認爲是「恰當」的即:架構
在沒有/最小的RPC通訊請求/服務之間的應答
每一個服務都封裝了持久性
每一個服務都表示一個功能,沒有「數據庫服務」
若是其中任何一個假設不存在,則結論可能就是無效的。
Martin Fowler在分享中強調了近年來「技術趨勢」的一些方面:備受矚目的是關於「微服務」的架構模型,屬於的正是定義,以及經過對需求的仔細分析和項目的狀況所產生的問題。less
固然,問題不在於用何種架構模式,而是在於爲特定的場景提供解決方案,及應用時缺乏匹配的需求。機器學習
技術推進了微服務的快速落地,近年來出現的新興技術每每都已經被微服務架構所採納,好比:異步
重要的是,當涉及到估值時,對於須要解決的目標和問題,必須很是清楚地認識到微服務所帶來的轉變,這裏簡短地回憶一下:編程語言
快速構建於組件級,項目的可管理性。
很是清晰和嚴格的界限。
部署獨立性和服務質量。
多語言編程/持久性的可能性。模塊化
其實咱們每每低估了每一個微服務須要的運營成本:
交付的政策。函數式編程
儘管像Docker和Jenkins的DSLs這樣的技術在使上述觀點能夠複製的過程當中起到了很大的做用,但運營成本與相比是不可能的:函數
更多的管道須要更多的硬件和計算資源。
爲了驗證交互,須要等待多個通道。
複製/看到Bug修復也是同樣的。
這些觀點受到邊界問題的影響(見下文)。
另外,爲了避免重複支持性和可操做性的方面,須要提取公共庫,並對全部公共代碼進行相同的處理。
這將從項目的0點增長解決方案的複雜性,生成通道之間的依賴關係,並生成私有存儲庫的需求。
從自動化/系統標準化的角度來看,下降運營成本須要一個較強的文化。這一般不是在一個項目中生成的。
能夠看到的是,儘管付出了努力,許多微服務體系結構並無獲得它們所須要的操做基礎設施支持。
與其餘方面同樣,若是向微服務遷移是漸進的,那麼標準化工做更有效率,而操做方面天然也會從服務的提取中「浮現出來」。
正如上面所提到的,微服務系統仍然是一個複雜的系統,它不只僅是簡單的部分。
假設已經支付了操做和標準化成本,而且微服務的邊界相對穩定。
在開發過程當中,反饋週期能夠與組件級的總體系統相媲美,但很重要的一點是,要清楚的是,在組件級別的反饋和組件組成的反饋之間要有一個平衡,這將會更加複雜。
對於系統級的任何問題,必須在消息傳遞中尋找它,調試困難。若是出現性能問題,這個問題會變得更加嚴重。消息一般是無類型的,將問題從編譯時移到運行時。解決一個問題,被測試,可能須要從新編譯/重建的一個或多個組件。
若是複雜性不在組件中,那麼它就必然在組件之間的交互中。這就是Martin Fowler所說的「智能服務,Dumb Pipes」的原則。「當替換/更新一個微服務的實例時,最小化依賴關係。」
更爲廣泛的是,啓發式對封裝的概念再次做出響應:「智能」越分散,系統就越模塊化。
儘管對使用支持異步通訊(Message Broker)的技術提供了無條件的支持,但不可否認,兩行代碼的調試會話和某種類型的總線之間的交互的成本是不一樣的。
一個微服務的從新定義(甚至重寫)的隱藏成本遠遠高於代碼庫的正常變化,其中包括:
業務成本的應用。
在不一樣生命週期的子系統中的鏡像/數據遷移。
協議的從新定義,公共API的不穩定性。
可測試性僅在集成級別上。
問題在於,正如埃裏克·埃文斯(Eric Evans)在《DDD Europe》的最後一版中指出的那樣,邊界的定義是很是複雜的,特別是在一個系統的進化開始的時候,它就像一個「有彈性的」。
惟一肯定的是,第一個設計對於項目的最新需求來講是錯誤的。此外,這個概念並不新鮮:它是敏捷方法論的基石。
從一開始使用微服務方法能夠保證在項目過程當中必須更改一個或多個(可能更多)的邊界。
這意味着「微服務溢價」將不可避免地獲得回報
每個變化的邊界,做爲改變的代價(見上文)。
當決定最小化邊界更改時,在服務之間的「會話」的倍增級別上,形成了可維護性甚至性能/可伸縮性的問題。
咱們認爲服務之間交互的數量和質量是面向服務架構的焦點,若是能夠用「Many Small Monoliths」來代替「微服務」。
具備總體架構的服務質量。
「可擴展性」在這種狀況下限制通用「可擴展性」不依賴鐵板一塊分佈與微服務但更多其餘屬性的更通常的人物,如缺少共享狀態的服務或數據的分佈。
能夠想象一種狀況,即發展是一個單一的Codebase(「monolith」),但分佈是多樣化的。
所以,整個Monolith將部署在分發服務「用戶」的機器上,但只有用戶API被髮布。這容許部署相同的Monolith的不一樣版本。它將最小化物理分離的成本,但實現了部署的獨立性,這是從微服務體系結構中尋求的特性之一。
在沒有特別的「交流」架構的狀況下,這種模式在單一和微服務之間的過渡多是可行的。甚至能夠在須要迫切須要組件級可伸縮性的時候擺脫「麻煩」。
若是有那麼多問題,爲何要用微服務呢?
本文不是「反對」微服務架構。而是試着提升對所涉及的成本的認識,作出一個合理的決定。試圖強調的問題是,最初給微服務架構的簡單性的感知,是錯誤的和扭曲的。
很容易認爲一個從0開始的項目,縮小規模,是經過擴展一個系統來開始開發是最簡單的事情。問題是,在那一刻,要忘記全部隱藏的成本,由於微服務仍然是總體的一部分。
微服務的優點
更容易理解和維護:微服務經過將應用程序分解爲一組易於管理的服務,從而解決複雜性問題,這些服務的開發速度要快得多,並且易於理解和維護。
採用新技術:每一個服務都是獨立的,因此選擇編程語言更依賴於實際的問題,而不是在項目開始時作出的選擇。
故障隔離:微服務改善故障隔離,使應用程序在很大程度上不受單個服務的故障影響。
可伸縮和成本效益:隨着需求的增長,擴展服務成本很是高。例如,一個應用程序由兩個模塊組成——Auth和Product。因爲微服務體系結構,用戶能夠擴展任意一個服務(好比Product,而不影響Auth服務)。
此外,因爲AWS像汽車可伸縮服務同樣,在對特定服務的需求增長的狀況下,微服務是很是簡單且經濟的。
總體架構的優點
複雜性:在基於微服務的應用程序中,很難實現經過各類服務傳播的更改。在總體應用程序中,更新相應的模塊,添加更改並一次性部署它們,相對簡單。
可部署性:對於總體應用程序,全部更改均可以經過單個部署進行推送。相反,微服務應用程序一般使用各類服務。每一個服務都須要單獨配置、部署、縮放和監視,這增長了額外的開銷。
測試:若是一個功能依賴於各類服務,那麼測試它就變得很是複雜。在總體應用程序中,測試相對容易。
處理失敗:在一個總體應用程序中,組件內部鏈接在一塊兒,所以處理失敗要容易得多,由於每件事都是單個應用程序的一部分。在微服務應用程序中,開發人員須要處理服務之間的邏輯、互通訊和故障,這最終會增長複雜性。
結論
基於微服務的體系結構提供了許多處理複雜系統的方法,但也有其自身的挑戰和複雜性。以微服務爲基礎的架構很是有用,若是應用程序真的很大,很複雜,並且作了不少不一樣的事情。
儘管沒有適合全部狀況的解決方案,可是,對於簡單的應用程序,總體架構是更好的方法。