若是花時間瞭解一下 DDD 的歷史,就會發現 DDD 已經存在了很長時間,單單按照 Eric Evans 成書那一年算起也已經有超過 10 年的歷史了。但即便在剛開始的那幾年,DDD 也只能說是不溫不火,只是小圈子裏人們的談資,鮮少看到分享的文章(至少國內給個人感受如此)。有意思的是大約三年前開始,DDD 從新迴歸大衆的視野,不管是線上的文章也好,仍是線下的各個大會,DDD 成爲當仁不讓的主角之一。數據庫
這背後的緣由錯綜複雜,很難找出單一的解釋。不過細心的閱讀近幾年來的 DDD 相關文章,你會發現有個名詞以很高的頻率與 DDD 一同出現,它就是微服務。對於微服務的分歧其實很大,或褒或貶,雙方每每走向兩個極端。推崇微服務的人以爲這是解決大型系統混亂,耦合的一劑良藥,而反對的人以爲這只是架構師沒事找事,平添了許多複雜性卻沒有帶來有價值的收益。編程
其實不少新技術,新事物都是如此。誕生之初被寄予厚望,看上去有一統宇內八荒的氣勢。可是隨着問題的出現,就招來了更大的質疑,反而落入了低谷。直到隨着時間的流逝,那些真正的實踐者們篳路藍縷,腳踏實地的解決問題,讓這些技術從新回到大衆的視野中。雖然最近一年多談論微服務的少了,可是我看到的是更多微服務落地的項目,雖然並非每一個都很是完美,可是絕大部分都達到了預期目標(因此最近搞中臺的同窗們沒必要灰心,多作一些落地具體的方案纔是迴應質疑最好的方式)。服務器
之因此 DDD 與微服務經常同時出現,緣由在於 DDD 中的不少實踐可以幫助微服務更好的落地,完成的質量更高。不只是對於單個的服務,對於整個微服務的架構,DDD 都可以起到很好的指導。而例如事件驅動,CQRS 這樣源自 DDD 的模式,在微服務的上下文中顯得更爲合理,也可以真正的發揮自身的能力。微信
以前也有同窗但願我寫一些有關微服務的文章,因此我也剛好藉着 DDD 的機會分享一些 DDD 與微服務結合的心得與經驗,但願可以幫到有須要的人。這是系列的第一篇,我會把重點放在微服務上,而下一篇則會分享如何結合 DDD 作好微服務的拆分。在開始以前仍是須要提醒一句,在軟件架構方面並無所謂的銀彈,適合個人解決方案並不必定適合你,而你如今用的挺好的技術在將來可能成爲最大的瓶頸。因此在本身的實踐中,要學會獨立思考,不要選最流行的,而是要選最適合本身,能爲本身創造最大價值的方案。畢竟就像李文秀在書中末尾處所說的,「別人硬要給你的,就算好得不得了,我不喜歡,終究是不喜歡。」。架構
微服務是一種架構風格,與之對應的是單體架構。在討論微服務的優勢以前,不妨先看看單體架構有哪些優缺點,單單知己是不夠的,知彼也很重要。每一個開發者對單體架構都很熟悉,是咱們平常開發過程當中最普通,最多見的一種架構風格。說白了就是把相關功能都放在一個 codebase 下,編譯,測試,發佈都是以一個總體進行的。最大的優勢就是簡單,易操做。開發簡單,你們代碼庫一拉,就能在上面開發新功能了。端對端的測試也簡單,調用一個接口,看看數據庫數據是否符合預期便可。而發佈部署就更簡單了,若是是 Java 項目,一個 war 包或是 jar 扔到服務器上就好了。運維
可是隨着項目業務的發展,規模的變大,單體架構的缺點就凸顯出來了。想象一下一個項目中存在着上萬個源文件,後臺數據庫中有上千的表,單單編譯一次可能就須要十幾分鐘的時間,跑一次完整的單元測試那更是萬萬等不起,這樣還能搞敏捷,搞 DevOps 嗎?誠然單體架構的系統一樣經過 DDD 這樣的架構模式提高可維護性,但這也是有上限的,隨着代碼的愈來愈多,業務邏輯的愈來愈複雜,項目的墒只會增長,最終難逃架構腐化,系統模塊間緊密耦合,開發人員不敢動遺留代碼的結局。分佈式
解決軟件複雜度的方法有不少,其中咱們最熟悉也是最熟練的就是分治。咱們將能夠複用的代碼放入不一樣的函數中,將一系列有關的行爲與數據放入類中,這是代碼層面的分治。咱們將多個相關功能的類放入到模塊中,造成了多個不一樣的編程模塊則是更高一層,在模塊層面的分治。對於單體架構面臨的問題,一樣能夠經過分治來解決,即把拆分的層次再向上移動一層,將一個大型的系統拆分紅多個服務,而這也就是微服務架構了。函數
在談及微服務時,咱們須要明確,咱們如何定義微服務呢?比較常見的誤區是把注意力集中在了微字上,例如曾經看到文章說須要把每一個服務的代碼限制在幾百行如下,源文件不得超過多少個纔算微服務。我本身以爲這有照本宣科的意思,其實微服務的特色在於鬆耦合與完整的服務這兩項上。微服務
咱們先看鬆耦合,這意味着服務應該是獨立的,能夠獨立開發,獨立測試,獨立部署,不依賴於任何的外部系統(基礎設施除外)。當其餘系統發生問題時,當前的服務依然能夠向外部提供部分服務,而不是向單體應用那樣,若是當前系統存在相似內存泄漏這樣的問題,會致使整個系統的響應時間變慢,將問題蔓延至其餘模塊。單元測試
同時鬆耦合也使得快速迭代,上線成爲可能,不須要在等待其餘模塊開發完成,就可以獨立的進入開發,生產環境。而這也會影響到你的版本管理的分治策略,你能夠很方便的使用基於主幹的分支管理策略,不須要擔憂長期存在的 feature 合併時發生使人頭疼的衝突問題。
其二是完整的服務。從業務功能的角度出發,每一個微服務都應該提供一組獨立,完備的業務服務。這也是不少時候讓架構師難以把握的方面,怎麼樣纔是獨立,完備,書上是找不到答案的,更多的時候這更像是一門藝術而不是技術。可是也不用過於擔憂,DDD 剛好可以經過限界上下文,核心域這樣的概念幫助咱們不斷的完善服務劃分。這也會在以後的服務拆分的篇章中詳細講解。
答案很明顯,微服務不是萬能的,甚至在有些場景下會放大原有團隊的缺點和問題,致使系統的穩定性變的更差。天底下沒有免費的午飯,在引入鬆耦合這些優勢以後,微服務帶來的是更復雜的系統架構,對於團隊,基礎設施,運維更高的技術要求,若是整個團隊或是組織沒法知足這些要求,沒法妥善的處理微服務帶來的反作用,那麼作好的選擇就是先提高內部能力再考慮架構的升級。
一個比較常見的場景是分佈式事務的問題。單體架構通常都使用關係型數據庫做爲數據存儲機制,經過關係型數據庫的事務機制來保證數據的一致性。可是在引入微服務以後,對應的數據庫也會進行拆分,甚至使用其餘類型,例如 NoSQL 這樣的數據存儲,所以並無辦法保證嚴格的數據一致性,須要引入 BASE 這樣的柔性事務,達到數據的最終一致性。若是一個團隊沒有在前期最好足夠的調研,並採起逐步替換策略,那麼極可能在架構遷移的第一階段就遇到巨大的障礙。
另外一個常見的問題則是對於基礎設施和運維的挑戰。在本來單體架構的場景中,運維和發佈的步驟很簡單,經過一些簡單的腳本就能完成自動化的發佈。可是在微服務架構中你須要面對的多是上百個容器的監控,幾十個服務之間調用鏈的分析和追蹤,當出現問題時須要在極短的時間內定位到問題。若是在這方面缺少積累,那麼就會出現線上有問題都不知道是那個服務引發的尷尬場面。
說了這麼多,關鍵點在於不要盲目的迷信某種技術架構,選擇合適本身的最重要。若是選擇了微服務,那麼開始以前先了解微服務架構有哪些必要的先覺條件,評估本身是否知足這些條件以後再考慮下一步的計劃。最後 DDD 中的不少模式可以幫助你理清微服務中的許多問題,提供更好的解決思路,這也是我以後文章中會詳細談及的,但願感興趣的不會錯過吧。
歡迎關注個人微信號「且把金針度與人」,獲取更多高質量文章