從單體架構到微服務架構演進


簡介

隨着互聯網的發展,互聯網企業的業務也在不斷的飛速發展,進而導致系統的架構也在不斷的發生着變化。總體來說,系統的架構大致經歷了:單體應用架構—>垂直應用架構—>分布式架構—>SOA架構—>微服務架構的演變。當然,很多互聯網企業的系統架構已經向Service Mesh(服務化網格)演變;

單體應用架構

在企業發展的初期,一般公司的網站流量都比較小,只需要一個應用,將所有的功能代碼打包成一個服務,部署到服務器上就能支撐公司的業務。這樣也能夠減少開發、部署和維護的成本。
比如,大家都很熟悉的電商系統,里面涉及的業務主要有:用戶管理、商品管理、訂單管理、支付管理、庫存管理、物流管理等等模塊,初期我們會將所有模塊寫到一個Web項目中,然后統一部署到一個Web服務器中。

優點

  • 架構簡單,項目開發和維護成本低。
  • 所有項目模塊部署到一起,對於小型項目來說,維護方便。

缺點

  • 所有模塊耦合在一起,雖然對於小型項目來說,維護方便。但是,對於大型項目來說,卻是不易開發和維護的。
  • 項目的各模塊之前過於耦合,如果一旦有一個模塊出現問題,則整個項目將不可用。
  • 無法針對某個具體模塊來提升性能。
  • 無法對項目進行水平擴展。

垂直應用架構

隨着企業業務的不斷發展,發現單節點的單體應用不足以支撐業務的發展,於是企業會將單體應用部署多份,分別放在不同的服務器上。但是,此時會發現不是所有的模塊都會有比較大的訪問量。如果想針對項目中的某些模塊進行優化和性能提升,此時對於單體應用來說,是做不到的。於是乎,垂直應用架構誕生了。

垂直應用架構,就是將原來一個項目應用進行拆分,將其拆分為互不想干的幾個應用,以此來提升系統的整體性能。

這里,我們同樣以電商系統為例,在垂直應用架構下,我們可以將整個電商項目拆分為:電商交易系統、后台管理系統、CMS管理系統等。

我們將單體應用架構拆分為垂直應用架構之后,一旦訪問量變大,我們只需要針對訪問量大的業務增加服務器節點即可,無需針對整個項目增加服務器節點了。

優點

  • 系統進行了拆分,可根據不同系統的訪問情況,有針對性的進行優化。
  • 能夠實現應用的水平擴展。
  • 各系統能夠分擔整體訪問的流量,解決了並發問題。
  • 一個系統發生了故障,不應用其他系統的運行情況,提高了整體的容錯率。

缺點

  • 拆分后的各系統之間相對比較獨立,無法進行互相調用。
  • 各系統難免存在重疊的業務,會存在重復開發的業務,后期維護比較困難。

分布式架構

我們將系統演變為垂直應用架構之后,當垂直應用越來越多,重復編寫的業務代碼就會越來越多。此時,我們需要將重復的代碼抽象出來,形成統一的服務供其他系統或者業務模塊來進行調用。此時,系統就會演變為分布式架構。
在分布式架構中,我們會將系統整體拆分為服務層和表現層。服務層封裝了具體的業務邏輯供表現層調用,表現層則負責處理與頁面的交互操作。

優點

  • 將重復的業務代碼抽象出來,形成公共的訪問服務,提高了代碼的復用性。
  • 可以有針對性的對系統和服務進行性能優化,以提升整體的訪問性能。

缺點

系統之間的耦合度變高,調用關系變得復雜,難以維護。

SOA架構

如果大家看過動漫《工作細胞》,一定會對萌萌噠的血小板妹妹印象深刻,《工作細胞》通過動漫擬人的方式講述了人體中不同細胞的職責和工作方式。每種細胞都有自己獨特的功能,血小板負責止血和修復創傷,而T細胞負責吞噬異物和發現入侵者。

軟件系統變得越來越復雜,參與的開發者就越多,應用系統的分離和分化就變得很有意義了。面向前端的API應用服務器不再真正的處理業務邏輯而是調用專門的服務器來完成。

單點登錄(SSO)是一個典型的面向服務的架構,在互聯網公司中被廣泛使用。國內互聯網巨頭往往擁有多個系統,例如騰訊的QQ音樂、空間都可以使用同一個QQ號登陸。於是用戶服務和認證服務被剝離開來,各個系統之間通過統一登錄和管理用戶信息,用戶的體驗得到了極大的提升,這就是面向服務架構的一個例子。​

在分布式架構下,當部署的服務越來越多,重復的代碼就會越來越多,對於容量的評估,小服務資源的浪費等問題比較嚴重。此時,我們就需要增加一個統一的調度中心來對集群進行實時管理。此時,系統就會演變為SOA(面向服務)的架構。

優點

使用注冊中心解決了各個服務之間的服務依賴和調用關系的自動注冊與發現;

缺點

  • 各服務之間存在依賴關系,如果某個服務出現故障可能會造成服務的雪崩;
  • 服務之間的依賴與調用關系復雜,測試部署的困難比較大

緩存穿透

首先,我們來說說緩存穿透。什么是緩存穿透呢?緩存穿透問題在一定程度上與緩存命中率有關。如果我們的緩存設計的不合理,緩存的命中率非常低,那么,數據訪問的絕大部分壓力都會集中在后端數據庫層面。

什么是緩存穿透?
如果在請求數據時,在緩存層和數據庫層都沒有找到符合條件的數據,也就是說,在緩存層和數據庫層都沒有命中數據,那么,這種情況就叫作緩存穿透。

我們可以使用下圖來表示緩存穿透的現象。

造成緩存穿透的主要原因就是:查詢某個Key對應的數據,Redis緩存中沒有相應的數據,則直接到數據庫中查詢。數據庫中也不存在要查詢的數據,則數據庫會返回空,而Redis也不會緩存這個空結果。這就造成每次通過這樣的Key去查詢數據都會直接到數據庫中查詢,Redis不會緩存空結果。這就造成了緩存穿透的問題。

如何解決緩存穿透問題?
既然我們知道了造成緩存穿透的主要原因就是緩存中不存在相應的數據,直接到數據庫查詢,數據庫返回空結果,緩存中不存儲空結果。
那我們就自然而然的想到了第一種解決方案:就是把空對象緩存起來。當第一次從數據庫中查詢出來的結果為空時,我們就將這個空對象加載到緩存,並設置合理的過期時間,這樣,就能夠在一定程度上保障后端數據庫的安全。

第二種解決緩存穿透問題的解決方案:就是使用布隆過濾器,布隆過濾器可以針對大數據量的、有規律的鍵值進行處理。一條記錄是不是存在,本質上是一個Bool值,只需要使用 1bit 就可以存儲。我們可以使用布隆過濾器將這種表示是、否等操作,壓縮到一個數據結構中。比如,我們最熟悉的用戶性別這種數據,就非常適合使用布隆過濾器來處理。

緩存擊穿

如果我們為緩存中的大部分數據設置了相同的過期時間,則到了某一時刻,緩存中的數據就會批量過期。

什么是緩存擊穿
如果緩存中的數據在某個時刻批量過期,導致大部分用戶的請求都會直接落在數據庫上,這種現象就叫作緩存擊穿;

我們可以使用下圖來表示緩存擊穿的線程;

造成緩存擊穿的主要原因就是:我們為緩存中的數據設置了過期時間。如果在某個時刻從數據庫獲取了大量的數據,並設置了相同的過期時間,這些緩存的數據就會在同一時刻失效,造成緩存擊穿問題。

如何解決緩存擊穿問題?
對於比較熱點的數據,我們可以在緩存中設置這些數據永不過期;也可以在訪問數據的時候,在緩存中更新這些數據的過期時間;如果是批量入庫的緩存項,我們可以為這些緩存項分配比較合理的過期時間,避免同一時刻失效。

還有一種解決方案就是:使用分布式鎖,保證對於每個Key同時只有一個線程去查詢后端的服務,某個線程在查詢后端服務的同時,其他線程沒有獲得分布式鎖的權限,需要進行等待。不過在高並發場景下,這種解決方案對於分布式鎖的訪問壓力比較大。

緩存雪崩

如果緩存系統出現故障,所有的並發流量就會直接到達數據庫。

什么是緩存雪崩
如果在某一時刻緩存集中失效,或者緩存系統出現故障,所有的並發流量就會直接到達數據庫。數據存儲層的調用量就會暴增,用不了多長時間,數據庫就會被大流量壓垮,這種級聯式的服務故障,就叫作緩存雪崩。

我們可以用下圖來表示緩存雪崩的現象。

造成緩存雪崩的主要原因就是緩存集中失效,或者緩存服務發生故障,瞬間的大並發流量壓垮了數據庫

如何解決緩存雪崩問題
解決緩存雪崩問題最常用的一種方案就是保證Redis的高可用,將Redis緩存部署成高可用集群(必要時候做成異地多活),可以有效的防止緩存雪崩問題的發生。

為了緩解大並發流量,我們也可以使用限流降級的方式防止緩存雪崩。例如,在緩存失效后,通過加鎖或者使用隊列來控制讀數據庫寫緩存的線程數量。具體點就是設置某些Key只允許一個線程查詢數據和寫緩存,其他線程等待。則能夠有效的緩解大並發流量對數據庫帶來的巨大沖擊。

另外,我們也可以通過數據預熱的方式將可能大量訪問的數據加載到緩存,在即將發生大並發訪問的時候,提前手動觸發加載不同的數據到緩存中,並為數據設置不同的過期時間,讓緩存失效的時間點盡量均勻,不至於在同一時刻全部失效。

微服務架構

隨着業務的發展,我們在SOA架構的基礎上進一步擴展,將其徹底拆分為微服務架構。在微服務架構下,我們將一個大的項目拆分為一個個小的可以獨立部署的微服務,每個微服務都有自己的數據庫。

優點

  • 服務徹底拆分,各服務獨立打包、獨立部署和獨立升級。
  • 每個微服務負責的業務比較清晰,利於后期擴展和維護。
  • 微服務之間可以采用REST和RPC協議進行通信。

缺點

  • 開發的成本比較高;
  • 涉及到各服務的容錯性問題;
  • 涉及到數據的一致性問題;
  • 涉及到分布式事務問題;

如何從單體架構過渡到微服務

架構師們最想通過微服務化取代的部分,往往是架構中的核心功能,經常用飛行中更換引擎來比喻。

為使微服務能順利的應用,不應該幻想一蹴而就,可以分階段采取行動。

培訓先行

技術人都善於把面臨的問題變成技術問題,然后在自己最擅長的領域去把它解決。
這就造成一個悖論:能用技術解決的問題就不是問題,真正的問題在受限的情景下僅靠技術是解決不了的,實施微服務最大的攔路虎也不是技術本身。
最大的問題不是如何做好微服務,而是就微服務應該是什么達成一個一致的看法。
因此,可以在實施前通過多數人參與大討論或培訓,使認知達成一致。這類似編碼規范中的命名規范,使用那種命名方法不重要,重要的是人人都使用同一種命名方法。

絞殺者模式

絞殺者模式是指,對於無法通過修繕者模式改進的系統,在系統外重新構建新功能來逐步剝離重構,對功能服務逐個絞殺。
好處是不影響原來的環境,一旦條件成熟就能快速切換。而缺點是可能需要一段時間同時維護兩套系統,付出額外的開發維護成本。

監獄模式

允許一些短期無力改動的系統通過監獄窗口(MicroProxy)接入微服務平台並委托 Proxy 將其暴露成微服務,單體架構往往擁有龐大的服務接口梳理, 往往需要開多個監獄窗口。

每個監獄窗口都會被包裝分割成微服務,條件成熟了能很方便的替換成原生微服務,稱為刑滿釋放。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM