點贊再看,養成習慣,微信搜一搜【三太子敖丙】關注這個文縐縐的程序員。
本文 GitHub https://github.com/JavaFamily 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。
前言
之前寫了一篇秒殺系統的文章,最后給自己埋了分布式事務的坑,然后很多讀者就要求我去寫分布式事務,那作為程序員屆的暖男,我一向是有求必應的,就算是不睡覺我都要寫給你們看的!

因為分布式事務是:分布式 + 事務 = 分布式事務。
理所當然的要先談談分布式,而分布式又得談談這個概念是如何演進得來的,因此作為創作鬼才的我,就先來講講架構的演進,什么叫分布式?什么是集群?SOA、微服務這兩個東西的關系和區別,下篇再講分布式事務。
因為我發現我讀者大多都是學生或者跟我一樣剛畢業不久,那一直聽分布式估計都聽膩了,估計都還不知道分布式的一些細節和架構演進路線吧。

先來說個題外話,我一直追崇一個技術點不僅要理解其原理,還需要知道這個技術點解決了哪些痛點,這些痛點又是由什么引發的?這個技術還未誕生的時候是如何解決的?
也就是整體的演進過程,歷史脈絡。
比如為何需要HTTP?HTTP0.9為何需要演進到HTTP1.0? 進而又向1.1、2演進到最新要將Google開發的基於UDP的QUIC協議應用到HTTP3中。
搞懂這些來龍去脈相信你不僅僅對HTTP會有更深層次的理解,對網絡也會有更加深刻的認識。當然也不是說一樣東西一來就得全盤理清,有些東西還是比較復雜的,只是說我們要往這個方向去學。
這也是我一直覺得很重要的一個學習思想,知其然知其所以然,會讓大家更好的理解很多東西。
一般架構的演進過程
好了,讓我們回到今天的主題,咱們先來看看一般架構的演進過程。
為什么說一般呢?舉個例子,比如某線下龍頭企業,現在想開展網上相關業務,那么有大批線下忠實用戶的支撐,並且自身錢包鼓鼓,人力財力都不缺。
那么線上的軟件架構就得考慮清楚了,幾乎不可能按照初始階段來,當然也不能用力過猛,實際得靠架構師以及團隊實力進行權衡。

單體應用架構
什么是單體應用?簡單的說就是不管啥功能都往一個應用里寫,比如電商系統。用戶功能、商品功能、訂單功能等等,都往一個應用里寫。
這有什么好處?
在項目初期,小公司人力財力不足,急於拓寬市場,這種單體應用架構簡單粗暴,將所有的功能都打包在一個的應用中,直接部署。
本地開發調試方便,直接起一個項目,調試也是在一個進程內,沒有冗長跨進程的調用鏈,出錯可快速定位。
本地的函數調用,沒有網絡調用的開銷。
線上出了問題回滾這一個應用即可(這一點其實在某種程度上看是優點,某種程度上看是缺點)。
總結的說就是開發、測試、部署方便,本地調用對於遠程調用性能較好。

有什么壞處?
系統耦合性高,導致開發效率低下。
一開始可能模塊結構還很清晰,隨着需求日益增長,不斷的添加新功能,代碼量巨增,模塊之間的邊界開始模糊,調用關系開始混亂,整體的代碼質量非常依賴個人水平。
假使某個同事水平較差,實現的代碼冗余,邏輯混亂,這時候要在上面添加新功能或者修改老功能其實是一件很困難的事情,你不能保證你修改的功能模塊不會影響到其他功能。
而且代碼會有**“破窗效應”**(這里其實不僅僅是單體架構,對於所有架構來說都是如此,只是單體應用更大的龐大,業務界限不清晰,因此這種問題更容易被放大)。
有些人看到這就可能會說,這上面還說開發方便,這就又效率低下了?是的,過猶不及。
再比如一個新需求上線例如短信相關的,並且訂單也做了一些改造,但是短信功能出了 bug,需要回滾的是整個應用,訂單模塊冤啊,陪着一起回滾。
我在老東家做電商活動,我們上線一個需求可能涉及6、7個服務,回滾也得全部回滾,而且都是負載均衡的,那機器可能就是上百台了。
語言單一,不能根據場景選擇更加合適的語言,例如要實現數據分析,應用的語言是 Java,那么就不能利用到 Python 豐富的類庫。
系統的整體可靠性不高,什么意思呢?還是拿短信功能說事,新上的短信功能寫的有 bug,不管是堆棧溢出還是死循環等等,核心的訂單等功能都會受到影響。 因此你上線的功能有問題影響的不僅僅是這個功能模塊,可能是整體系統的癱瘓。

系統不易於擴展部署,假設你發現你們的商品查詢的流量特別大,頂不住就得加機器。因為是單體應用所以為了商品查詢這一個功能,你需要在新加的機器上部署這一個應用,沒法單獨為這一個功能做定制化部署,對硬件資源有一定的浪費。
總結的說缺點就是隨着需求不斷增長,代碼結構日益復雜,各功能摻雜在一起,系統耦合性高,模塊之間邊界維護非常依賴開發者的個人水平。
模塊之間經常會有公共功能難以划分清楚,添加或修改功能困難,不確定是否會影響到其他模塊,所有功能都在一個進程內,某個功能出問題可能影響的就是整個應用,而且無法根據特點場景選擇更加合適的語言去實現功能,技術單一。
隨着用戶的增長,無法做到熱點功能單獨擴展,只能整體應用部署。
至此我們已經明白了單體應用架構的優缺點,可以看出初始階段單體應用優點突出,隨着需求和用戶的增長漸漸的單體應用頂不住,缺點在不斷的放大。
也就是說你的產品需要發展到一定的階段,單體應用才會頂不住。在這之前單體應用是你的最佳選擇。
你要是說我的產品肯定頂的,所以一開始就大刀闊斧的設計,單體應用太 low 堅決不用。
可以的,秀出你的花樣,你有你的 Young。

我們再來看下單體應用一般的架構圖,注意單體應用不是真的就線上部署一個,好歹得兩台,互相 backup 下,不能太虎一台頂。

又過了一段時間,你發現你們還需要開發手機版。於是你們的架構又變成下圖所示的樣子。

沒錯,為了讓每個端不會相互影響,粗暴的拷貝現有的應用,稍加修改即可為手機版和小程序提供服務,你會發現很多功能代碼都是重復的。這時候來個需求你改的就是多份代碼了。
微服務架構
又過了段時間你已經強烈感受到單體應用所帶來的痛點,這證明你的產品發展的不錯,一開始肯定會忍,繼續忍,終有一天你會一拍桌子!來開個會咱們得還債了。
理所當然的你會根據不同業務拆分出不同的服務,並且會整理出當前公共的功能變成一個公共服務,每個服務獨立部署,獨立運行,代碼進行了物理隔離,一個小團隊維護一個服務或多個服務。
並且一般而言服務化了,數據庫也會拆分出來每個服務維護自己的數據庫,數據庫之間的數據通過接口傳遞,而不再是直接訪問。
此時你的系統變成了下圖所示的樣子。

那現在解決了單體應用什么問題?
系統的耦合度降低,模塊之間的邊界清晰,都按業務物理隔離了。
在一定的措施下(下文會提到),系統整體可靠性變高。
技術選型豐富,不同的服務可以利用不同的技術或語言實現,例如數據分析服務可以用 Python 實現,一些底層的服務團隊說我要用 GO,那就用 GO 唄。
可根據服務擴展部署,商品服務訪問量特大,那我們就單單給商品服務擴容,增加機器,其他服務照舊。
這就是微服務了。
好像微服務架構解決了單體應用的所有痛點啊?別急上面只是微服務的一部分,真正的微服務架構還需要包含很多東西,微服務是解決的單體應用的痛點,但是也引入了新的痛點!

服務化了之后上線某個需求,如果是單個服務內的不影響其它服務的你會感到很舒服,如果這個改動是接口層面的改動,涉及到多個服務,你就會覺得有點難受了。
上線之前需要定制好服務上線的順序,定制好每個服務的回滾計划,涉及到每個團隊之間的合作,上線不再是一個簡單的打包、部署的過程。
出了問題也不是一個簡單回滾的過程,而可能是各個團隊分別回滾各自的服務。如果你自己的服務出了問題你會很焦慮,別的團隊都等着。如果別的團隊出了問題你也焦慮,怎么還沒好啊。
你還會發現本地開發如果依賴別的服務會異常的難受,特別是你依賴的服務還依賴別人的服務,調試、測試將變的復雜。
而且你會發現調用鏈路變長,調用增加了網絡的開銷,性能變差。而且出錯難以定位問題來源。因此你需要引入分布式鏈路追蹤服務來定位問題。
還需要引入ELK來方便日志的查看,分析問題。
為了能夠動態擴容,你的服務需要自動注冊且能被自動發現,因此需要個注冊中心。
網絡之間的調用較為不可靠,因此還需要讓調用有重試機制,防止其他服務出 bug 或其他原因瘋狂調用你的服務,還需要有限流措施。為了防止一個服務掛了導致整體的雪崩需要有熔斷措施。
為了在特殊時候例如大促的時候讓出硬件資源給核心功能,還需要有降級策略。
上面說的重試、限流、熔斷、降級就是上文提到的一定措施下,可靠性變高。
而且每個服務都需要配置,因此還得有個配置中心,來做統一管理。
服務太多了,調用關系復雜為了對調用者更加的友好,並且還需要對調用進行權限等控制,因此需要有個網關,對外暴露統一的接口,當然想限流什么的可以在網關實現。
當然整體的監控是必不可少的,對所有的服務都需要做到全面的監控。
其他的還有啥DevOps、容器等等。

可以看到服務化之后需要引入太多太多的東西,有人可能說你這也就才幾個服務啊,我上面的服務其實可以再細分。
例如商品的修改和寫入動作相比較於商品的瀏覽訪問量肯定少很多,那我就將商品的瀏覽再剝離出來單獨做一個服務,這樣便於擴容。
這用戶量上來,訪問量增加這樣的服務剝離你會發現越來越多,服務的數量到時候就上來了,而且需求也會不斷增加,推薦服務啊、搜索服務啊等等很多很多,只是為了簡便都沒列出來。
上面提到的那些服務於微服務的組件也得部署,也得保證可靠性...你看這系統就越來越復雜了,所以服務化之后解耦了業務,卻又融入了非業務相關的東西。
不過服務化其實是一個自然的結果,就像我們平時去的辦事大廳會根據服務類別划分成不同的服務窗口,為了辦一件事情我能可能需要在各個窗口之間來回走動,這對應的不就是調用鏈路長嘛?走動的耗時等於我們調用的網絡開銷。
所以說微服務架構是發展到一個階段自然而然的演進產物,早在微服務這個概念被提出之前,很多公司就已經是這樣干的了。
我上面提到的其實是微服務1.0架構,而微服務2.0就是為了將非業務功能剝離出來而提出的,將服務治理的功能放在 SideCar 即邊車上,使得開發者專注於應用業務的開發,進而演進出 Service Mesh 即服務網格架構。
SOA和微服務
談到微服務你會發現 SOA 這個名詞經常伴隨着出現。
關於SOA和微服務我查閱了很多資料,不過對於這兩個名詞的解釋都各執一詞,沒有一個統一的答案。今天我就說說我的理解,拋磚引玉,有紕漏之處,敬請指正。
SOA,全稱 Service-Oriented Architecture
即面向服務的架構。說到SOA就離不開 ESB,全稱Enterprise Service Bus
。SOA和微服務一樣都是面向服務的。

可以看到 SOA 架構通過企業服務總線進行交互,也就是說中心化,需要按照總線的標准進行開發改造,而微服務是去中心化的。
其實我們可以抓到關鍵字企業,SOA 我認為是企業級別的面向服務概念,而微服務是應用級別的概念。
兩種都是面向服務,只是 SOA 注重的是企業資源的重復利用,把企業的各個應用通過 ESB 進行整合。
而微服務注重的是應用級別的服務划分,使得應用內服務邊界清晰,易擴展。
這兩者其實是兩個方向的面向服務,互不沖突。還能是包容的結構,如下圖所示

分布式和集群
分布式可以認為是通過網絡連接多個組件而形成的系統。
廣義上說前后分離的應用就能算分布式,前端的 js 代碼在瀏覽器跑着,后端的代碼在服務器跑着,兩種不同的組件合力對外提供服務構成分布式。
而我們常提到的分布式是狹義上的,指代不同的組件通過協作構成的系統。
而集群常指的同一個組件多實例而構成邏輯上的整體。
這兩個概念不沖突,分布式系統里面可以包含集群,像我們的商品服務就可以是集群部署。
絮叨
今天主要簡述了下架構的演進,單體應用的優缺點以及微服務的優缺點。
再談了談SOA 和微服務之間的區別,以及分布式和集群的區別。
說了這么多,也不知道有沒有說清楚,個人能力有限,如果有紕漏,敬請指正,分布式事務也在瘋狂爆肝中,我們下篇文章見。
另外,敖丙把自己的面試文章整理成了一本電子書,共 1630頁!目錄如下,還有我復習時總結的面試題以及簡歷模板

現在免費送給大家,在我的公眾號三太子敖丙回復 【888】 即可獲取。

我是敖丙,你知道的越多,你不知道的越多,我們下期見!
人才們的 【三連】 就是敖丙創作的最大動力,如果本篇博客有任何錯誤和建議,歡迎人才們留言!
文章持續更新,可以微信搜一搜「 三太子敖丙 」第一時間閱讀,回復【資料】有我准備的一線大廠面試資料和簡歷模板,本文 GitHub https://github.com/JavaFamily 已經收錄,有大廠面試完整考點,歡迎Star。