SpringCloud—架構演變之SpringCloud由來

語言: CN / TW / HK

學習目標

  1. 回顧架構的演進。
  2. 明確springcloud是什麼?
  3. 明確spring、springboot和springcloud之間的關係。
  4. 瞭解springcloud的常用元件及其作用。

第1章 架構演進

1、單體架構

我相信,絕大部分同學都用過SSM框架進行過開發,當時你們所在專案組肯定是將所有的功能模組全部放在了同一個框架裡面,只是不同的功能建了一個不同的包,然後所有的功能模組資料儲存在一個數據庫裡面,然後通過一臺Tomcat容器去啟動服務。

這種架構在最開始公司業務量、資料量、併發量小的情況下是沒問題的,甚至對於開發人員更友好。

但是來了,但是隨著你公司的發展,業務量增大,功能需求增多,資料量併發量也增大的時候,單體架構就不行了,為什麼呢?

  1. 隨著業務量增大,單臺Tomcat很容易達到效能瓶頸,一般的伺服器上Tomcat的最大併發量也就在200左右。
  2. 因為只有一臺伺服器,出現問題就直接掛掉了,此時客戶端都訪問不了服務,這個時候就讓我想起了,讀大學的時候選選修課,每次都要等好幾個小時才能選上,體驗極差。

2、叢集架構

為了解決上面的這些問題,必須要從根源上進行優化。此時叢集架構出現。

叢集架構的邏輯其實很簡單,它就是把整個系統從一臺伺服器上部署變成了多臺伺服器部署,只是對整個系統的複製拷貝。然後增加Nginx伺服器做負載均衡而已。

但是叢集架構也存在一些問題:

  1. 如果系統中的某個很小的功能發生了版本迭代,那這個時候就需要將所有的系統全部停掉,然後進行更新。而且可能整個系統非常龐大了,開發這個大系統的部門人員可能也非常多組織架構也不好管理。
  2. 雖然你係統做了叢集,但是資料庫往往才是制約你係統效能的最大因素,當併發量大了,資料量大了,資料庫是處理不過來的。

3、業務垂直化拆分

針對上面的問題,架構再一次需要改進,整個大系統不適用了,就將不同的功能模組拆分成小系統。

對業務進行垂直化拆分,簡單來說,就是可以按照系統的業務功能拆分出多個業務模組子系統。每個子系統由不同的業務團隊負責。

4、服務化改造

隨著對業務系統進行垂直化改造之後,以業務功能緯度拆分出來多個子系統,而在各個子系統中,會存在比較多的共享業務,比如使用者資訊查詢,在支付業務中會涉及到、在首頁中也會涉及到。那麼勢必會造成重複開發產生非常多的冗餘程式碼。那麼這個時候就引入了服務化改造的思想,也就是 SOA把一些通用的、會被多個上層服務呼叫的模組獨立拆分出來,形成一些共享的基礎服務。這些被拆分出來的共享服務相對來說是比較獨立,並且可重用。 比如使用者管理服務,包含使用者註冊、使用者查詢等功能。比如單點登入服務;

SOA 的核心目標就是通過服務的流程化來實現業務的靈活性,而這個流程化其實就是由一系列相關聯的任務組成,這一系列相關聯的任務可以通過一系列的服務組合來實現具體的業務功能SOA 面向服務架構,從語義上說,它與面向過程、面向物件、面向元件一樣,是一種軟體組建及開發的方式。所以在 SOA 中,服務是最核心的抽象手段,業務被劃分為一些列粗粒度的業務服務和業務流程

SOA 中更強調 ESB 企業服務匯流排,企業服務匯流排可以使得服務之間的互動是動態的,以及服務位置是透明的。這樣的好處是服務的呼叫者和服務的提供者之間是高度解耦的。從而使得服務有更高的靈活性以及隔離性。

ESB: 是從面相服務架構(SOA)發展過來的,主要是對多個系統中的服務呼叫者和服務提供者的解耦。ESB 本身提供了服務暴露、接入、協議轉化、資料格式轉化、路由等功能。

SOA 主要解決的問題:

  1. 資訊孤島。
  2. 互聯互通。
  3. 業務重用。

5、微服務架構

業務系統實施服務化改造後,原本共享的業務被拆分,形成可複用的服務,可以在最大程度上避免共享業務的重複建設、資源連線瓶頸等問題出現。那麼那些被拆分出來的服務,是否也需要以業務功能為維度來進行拆分,使之能夠獨立進行部署,以降低業務藕合和提升容錯性呢?

微服務並不是一種新思想的方法。它更像是一種思想的精煉,是一種服務化思想的最佳實踐方向而已,所以我認為微服務其實是在 SOA 思路下,隨著各個企業對於服務化治理上不斷地完善,以及對軟體的交付鏈路以及基礎設施逐步成熟之下的一種自然的產物。 微服務也是一種面向服務的架構模型,只是它更強調服務的粒度。也就是服務的職責更加單一更加精煉我們也可以把 SOA 看成是微服務的超集。 也就是多個微服務可以組成一個 soa 服務。

6、微服務和 SOA 架構的區別

經常會有同學問,微服務和 SOA 架構有什麼區別。這個區別一定要從架構的發展過程來了解。這兩種架構模式,其實本質上應該是在分散式架構這條時間線上,基於服務化思想的不斷完善,以及基礎設施的逐步成熟之下的一種升級。既然存在於時間線的先後,那也就意味著,這兩種架構模式所關注的點不一樣

SOA

MSA(微服務)

遵循“儘可能多地共享”架構方法

遵循“儘可能少地共享”架構方法

重要性在於業務功能重用

重要性在於“有界上下文”的概念

他們有共同的治理和標準

他們注重人、合作和其他選擇的自由

使用企業服務匯流排(Enterprise Service bus,ESB)進行通訊

簡單訊息傳遞系統

它們支援多種訊息協議

使用輕量級協議,如HTTP/REST等

具有更多開銷的多執行緒來處理I/O

單執行緒通常使用事件迴圈特性來進行非鎖定I/O處理

最大限度地提高應用程式服務的可重用性

重點在於解耦

傳統的關係資料庫更常用

現代的關係資料庫更常用

一個系統性的改變需要修改整體

一個系統性的改變是創造一個新的服務

DevOps/Continuous Delivery正在變得流行,但還沒有成為主流

人們強烈關注DevOps/Continuous Delivery

第2章 Spring Cloud

上一章講到了架構的演進過程,事實上不管什麼架構,都是需要通過合適的框架技術進行落地,從最開始的spring框架,到後來的springboot,再到現在的springcloud,那為什麼需要springcloud呢?spring為什麼不行呢?

要想整體弄明白這些問題,那我們接下來先弄清楚幾個概念,自己在腦海裡面形成一套體系:

  1. spring在開發過程中有什麼問題?
  2. springboot的出現解決了什麼?
  3. springboot跟springcloud是什麼關係
  4. springcloud是什麼?它包含了什麼?

1、spring的問題

事實上spring的出現就是為了簡化開發的,spring的核心概念絕大部分同學都能說出來,無非就是3個,IoC、DI、AOP,下面稍微解釋一下這仨兄弟是幹嘛的。

  1. IoC實際上就是一個容器,它就是用來裝Bean物件的;回到最最基礎的層面,我們java開發就是在不斷的通過new建立物件,然後拿到物件之後呼叫物件裡面的方法。OK,那在實際開發過程中,如果所有的物件都需要手動去建立將是一個非常繁瑣的過程,也許你有1萬個類,然後這1萬個類在各種地方都要建立物件,這個時候假設用到了A類的物件,然後你在B類中new了物件,如果要在C、D、E等等類中要用到這個物件的話,將會很麻煩,這只是一種情況,在開發中這種類似的現象隨處可見,所以spring為了解決這個過程,設計了一個IoC的功能,你就理解成一箇中心容器,用來裝專案中幾乎所有需要用到的Bean物件。
  2. IoC的概念理解了,那麼這個時候你要想,物件建立了,但是物件裡面可能會存在別的一些成員屬性,而這些成員屬性又是另外的一些物件,舉個例子就是A物件裡面有個成員屬性是B物件,那這個時候你要去進行引用的關聯,這一步也非常麻煩和繁瑣,怎麼辦呢?spring的DI幫你完成了,在A物件new的過程中,spring就會去中心容器找有沒有B物件,有的話就把這個B物件賦值給A物件的屬性。
  3. AOP的概念其實更好理解,它是基於動態代理完成的,你們要清晰的指導,代理就是做增強的,什麼意思呢?假設有一個物件的業務功能就是建立訂單,OK,那我不想直接呼叫這個物件的建立訂單功能,我想在建立訂單之前和之後乾點別的事情,比如說列印日誌這個事,這個時候就用到了代理。

OK,spring基於這仨兄弟確實簡化了很多開發的流程,但是,在最開始的過程中spring在進行IoC注入物件的過程中,它是基於XML方式的,這個邏輯很容易理解,就是你要把什麼物件放到容器中去,只需要在XML檔案中配置一下就好了。

但是,正因為這個,使得spring變的無比的繁瑣,你想想,一個專案中得用到多少個物件,每個物件都去配置一下,完犢子了。要寫無數個XML檔案了。

spring開始發力,要優化了,引入註解,但是沒用啊,如果你專案要整合別的元件呢?比如redis,比如mybatis。甚至在微服務專案中要引入整合各種元件的話,那更加崩潰。

其實歸根結底,spring還是沒有解決IoC注入的複雜流程,以及外部化配置的統一管理。

2、springboot

看過springboot原始碼的同學都知道,springboot底層其實會走一遍spring的流程。也就是springboot依賴於spring,同時它也在spring的基礎之上作了一些工作。

具體作了啥,實際上就是解決IoC自動注入和配置統一管理,使得這個工作不再需要程式設計師去做了,框架自己幹了。具體怎麼解決的參照之前的內容。

3、springcloud生態

先明確springcloud是什麼?網上都說,啊呀springcloud就是做微服務的,它是一個生態啊等等。進說一些我們聽不懂的。

那我這裡用最簡單的語言去解釋一下:

springcloud就是springboot整合各種各樣starter元件的一個集體,springcloud底層核心框架就是springboot,然後springboot整合不同元件的時候不需要程式設計師去寫XML檔案以及配置檔案了,而是一些好事之徒,他們基於springboot自動裝配原理寫了starter元件,然後將這些starter元件和springboot的整體我們給了一個名字叫做springcloud。

明白了吧,那知道springcloud是什麼之後,在來看這個生態裡面包含了啥,springboot我知道了,starter元件有哪些呢?

這個不用去背,我們自己根據資料流向從整體上去串一串就好了,當你串明白了,那你離架構師就不是太遠了。

(1)閘道器

Gateway元件

我們知道 spring cloud 可以用來開發微服務,但是應該很少有同學真正知道 spring cloud 是什麼。

官方的解釋是:spring cloud 提供了一些可以讓開發者快速構建分散式應用的工具,這些服務可以很好的工作在任何分散式環境下。

既然提供的是一些快速構建微服務應用的工具,那麼我們需要了解微服務開發過程中需要解決哪些問題?

在微服務實施之後,各個服務的拆分粒度很小,對於客戶端來說,做一個操作可能會涉及到後端的多個服務元件的呼叫,那意味著它需要頻繁的發起多次訪問才能進行資料聚合實現使用者的功能。

如果我們在所有的微服務之前增加一個閘道器,對於客戶端來說它需要做什麼功能操作直接呼叫閘道器並且告訴閘道器所要做的事情即可,閘道器根據請求的功能對後端的多個服務的資料進行聚合聚合哦從而減少客戶端的呼叫頻次。

並且,由於有了閘道器的聚合,我們還可以在閘道器層對請求進行統一鑑權和認證; 包括還可以實現限流、請求日誌統一記錄、 灰度釋出等等。

(2)遠端通訊

Openfeign、Dubbo

服務拆分以後就會涉及到服務的遠端通訊,比如 http 協議或者 rpc 協議。

(3)服務發現

Eureka、Nacos

在滿足基礎通訊的基礎上,如何做到服務的統一管理以及服務的動態感知,就需要涉及到服務的註冊中心來實現服務註冊和發現的功能

(4)負載均衡

Ribbon、Dubbo

假設服務提供者為了擴大吞吐量,採用 10 臺機器的叢集部署,這個時候客戶端從註冊中心獲得服務以後,應該呼叫哪臺機器呢?

所以必然有一種負載均衡的機制,來實現客戶端請求的分發。

(5)熔斷、限流、降級

Hystrix、Sentinel

在分散式架構中,各個服務節點一定需要滿足高可用,所以對於服務本身來說,一方面是在有準備的前提下做好充足的擴容。另一方面,服務需要有熔斷、限流、降級的能力。

當一個服務呼叫另外一個服務,可能因為網路原因、或者連線池滿等問題導致頻繁出現錯誤,需要有一種熔斷機制,來防止因為請求堆積導致整個應用雪崩。

當發現整個系統的確負載過高的時候,可以選擇降級某些功能或某些呼叫,保證最重要的交易流程的通過,以及最重要的資源全部用於保證最核心的流程。

在設定了熔斷以及降級策略後,還有一種手段來保護系統,就是限流演算法。

我們能夠通過全鏈路壓測瞭解到整個系統的吞吐量,但實際上的流量可能會超過我們預期的值,比如存在惡意攻擊、或者突然的高峰流量。在這種情況下可以通過限流來保護系統不崩潰,但是對於部分使用者來說,會出現被限流導致體驗不好的情況。

(6)配置中心

Config、Nacos

服務拆分以後,服務的數量非常多,如果所有的配置都以配置檔案的方式放在應用本地的話,非常難以管理,可以想象當有幾百上千個程序中有一個配置出現了問題,是很難將它找出來的,因而需要有統一的配置中心,來管理所有的配置,進行統一的配置下發。

在微服務中,配置往往分為幾類,一類是幾乎不變的配置,這種配置可以直接打在容器映象裡面,第二類是啟動時就會確定的配置,這種配置往往通過環境變數,在容器啟動的時候傳進去,第三類就是統一的配置,需要通過配置中心進行下發,例如在大促的情況下,有些功能需要降級,哪些功能可以降級,哪些功能不能降級,都可以在配置檔案中統一配置。

(7)分散式事務

Seata

對於資料庫的垂直拆分,已經服務的拆分,單體的資料庫事務完全不能滿足需求了,這個時候就需要一個第三方的協調工具來做到統一管理事務提交回滾等操作,這個時候Seata出現了。

4、服務帶來的問題

(1)業務團隊的痛點

  1. 對於業務開發團隊而言,最強的是技術嗎?一定不是,業務團隊最強的一定是對於業務的理解和熟悉程度。
  2. 而業務應用的核心價值,就是為了實現業務場景,而不是寫微服務,微服務只是一種實現業務的手段。
  3. 業務團隊除了關心業務之外,他們所面臨的最大的挑戰在於,如何保證系統的穩定性何可擴充套件性、如何設計一個安全的 open api。如果對服務進行拆分、如何保證跨庫的資料一致性。以及對於舊系統的改造。
  4. 於公司層面而言,業務團隊的壓力還來自於時間人力的投入,我們用於被各種 deadline 趕著走。所以作為一個業務程式設計師,如果在這個 deadline 之前還需要花更多的時間投入在spring cloud 這些工具的學習上,那無疑是雪上加霜。公司對於業務團隊的考核,永遠只看結果!

(2)跨語言帶來的問題

微服務有一個很重要的特性,就是不同的微服務可以採用自己最擅長的語言來編寫程式。這種特性在企業中落地的時候又會帶來一些問題。

比如公司內部會開發一些公共的類庫或者框架,也或者會使用第三方的類庫或者框架來實現某些功能。

但是由於公司的微服務用了各種各樣的語言,那意味著這些類庫需要針對不同的語言開發相容版本。如果是主流語言還好,如果是一些小眾語言,那對於這些基礎元件的開發者而言無疑是晴天霹靂.

(3)總結

從這些痛點中可以發現,我們所做的所有非業務類的事情,都是為了保證把請求傳送到正確的地方,並且能夠及時或得正確的結果。那對於對於業務開發人員而言,是否有必要去關心這些呢?

回到最開始我們說的一個例子,在進行計算機網路通訊的時候,開發人員有必要去關心網路通訊的細節嗎? 我們在使用 http 協議進行資料傳輸時,關心過底層是使用 TCP 還是 udp?資料是怎麼傳輸的?

既然我們不需要關心這些,那對於微服務架構中的這些問題,業務開發人員為什麼一定要關心服務的通訊呢?