隨著 IT 資訊化的普及,更多的交易放到了網路上,資訊量增加和訪問次數頻繁就是要解決的問題了。

因此,逐漸加入了快取、叢集等技術手段。同時對業務的擴充套件性和伸縮性的要求也越來越高。

高併發、高可用、可伸縮、可擴充套件、夠安全的軟體架構一直是架構設計追求的目標。

今天我們來看一下架構設計經歷了哪些階段,每個階段都解決了哪些問題,又引出了哪些新問題。

主要是引起大家的思考,在不同的業務發展階段採取合適技術手段,用變化擁抱變化是 IT 人追求的目標。

應用與資料一體模式

最早的業務應用以網站、OA 等為主,訪問的人數有限,單臺伺服器就能夠應付。

通常,將應用程式和資料庫部署到一臺伺服器上面

在這一階段,我們利用 LAMP(Linux Apache MySQL PHP)技術就可以迅速搞定,並且這些工具都是開源的。

很長一段時間內,有各種針對這種應用模式的開原始碼可以使用。這種模式基本上沒有高併發的要求,可用性也很差。

有的伺服器採用託管模式,上面就安裝了不同的業務應用,一旦伺服器出現問題,所有的應用就罷工了。

不過其開發和部署成本相對較低,適合剛剛起步的應用服務。圖 1 就描述了單個應用和資料庫執行在單臺伺服器的模式,我們稱這種模式為應用與資料一體模式。

應用與資料分離模式

隨著業務的發展,使用者數和請求數逐漸上升,伺服器的效能出現了問題。其中比較簡單的解決方案就是增加資源,將業務應用和資料儲存分開。

其中,應用伺服器需要處理大量的業務請求,對 CPU 和記憶體有一定要求;而資料庫伺服器需要對資料進行儲存和索引等 IO 操作,對磁碟的轉速和記憶體會考慮更多。

這樣的分離解決了效能的問題,我們需要擴充套件更多的硬體資源讓其各司其職,使系統可以處理更多的使用者請求。

雖然業務上依舊存在耦和,但硬體層面的分離在可用性上比一體式設計要好很多。

快取的加入

隨著資訊化系統的發展和使用網際網路人數的增多,業務量、使用者量、資料量都在增長。

我們同時發現,使用者會對某些資料的請求量特別大,例如新聞、商品資訊和熱門訊息。

之前這些資訊的獲取方式是依靠資料庫,因此受到資料庫 IO 效能的影響。此時資料庫成為了整個系統的瓶頸。

如果再增加伺服器的數量,恐怕也很難解決,於是快取技術就登場了

這裡提到的快取技術分為客戶端瀏覽器快取、應用伺服器本地快取和快取伺服器快取。

①客戶端瀏覽器快取

:當用戶透過瀏覽器請求伺服器的時候,會發起 HTTP 請求。如果對每次 HTTP 請求進行快取,那麼可以減少應用伺服器的壓力。

②應用伺服器本地快取

:它使用的是程序內快取,又叫託管堆快取。以 Java 為例,這部分快取放在 JVM 的託管堆上面,同時會受到託管堆回收演算法的影響。

由於它執行在記憶體中,對資料的響應速度很快,通常我們會把熱點資料放在這裡。

在程序內快取沒有命中的時候,會到快取伺服器中獲取資訊,如果還是沒有命中,才會去資料庫中獲取。

③快取伺服器快取

:它相對於應用伺服器本地快取來說,就是程序外快取,既可以和應用服務部署在同一伺服器,也可以部署到不同的伺服器。

一般來說,為了方便管理和合理利用資源,會將其部署到專門的快取伺服器上面。由於快取會佔用記憶體空間,因此這類伺服器會配置比較大的記憶體。

描述了快取請求的次序,先訪問客戶端快取,之後是程序內的本地快取,接下來是快取伺服器,最後才是資料。

如果在任意一層獲取了快取資訊,就不再往下訪問了,否則會一直按照這個次序獲取快取資訊,直到資料庫。

使用者請求訪問資料的順序為客戶端瀏覽器快取→應用伺服器本地快取→快取伺服器快取。

如果按照以上次序還沒有命中資料,才會訪問資料庫獲取資料。加入快取的設計,提高了系統的效能。

由於快取放在記憶體中,而記憶體的讀取速度比磁碟要快得多,能夠很快響應使用者請求。

特別針對一些熱點資料,優勢尤為明顯。同時,在可用性方面也有明顯的改善。

即使資料庫伺服器出現短時間的故障,快取伺服器中儲存的熱點或者核心資料依舊可以滿足使用者暫時的訪問。當然,後面還會對可用性進行最佳化。

伺服器叢集的加入

經過前面三個階段的演進,系統對使用者的請求量有了很好的支援。實際上,這都是在解決高效能和可用性的問題,這一核心問題會一直貫穿整個系統架構的演進過程中。

隨著使用者請求量的增加,另外一個問題又出現了,那就是併發。把這兩個字拆開了來看:並,理解為“一起並行“,有同時的意思;發,理解為“發出呼叫”,也就是請求的意思。

合起來就是多個使用者同時請求應用伺服器。如果說原來的系統面對的僅僅只是大資料量的話,那麼現在就需要面對多使用者同時請求。

如果還是按照上一個階段的架構圖推導,單個應用伺服器已經無法滿足高併發的要求了。

此時,伺服器叢集就加入戰場了

伺服器叢集也就是多臺伺服器扎堆的意思,用更多的伺服器來分擔單臺伺服器的負載壓力,提高效能和可用性。

再說白一點,就是提高單位時間內服務處理請求的數量。原來是一個伺服器處理,現在是一堆伺服器來處理。就好像銀行櫃檯一樣,增加櫃員的人數來服務更多的人。

這次架構演進與上次相比,增加了應用伺服器的個數,用多臺應用伺服器形成叢集。

應用伺服器中所部署的應用服務沒有改變,在使用者請求與伺服器之間加入了負載均衡器,幫助使用者請求路由到對應的伺服器中。增加伺服器的舉動表明,系統的瓶頸是在處理使用者併發請求上。

針對資料庫和快取都沒有做更改,這樣僅僅透過增加伺服器數量就能夠緩解請求的壓力。

伺服器叢集會透過多臺伺服器來分擔原來一臺伺服器需要處理的請求,在多臺伺服器上同時執行一套系統,因此可以同時處理大量併發的使用者請求。

有點三個臭皮匠頂個諸葛亮的意思,因此對叢集中單個伺服器的硬體要求也會降低。此時需要注意負載均衡均衡的演算法,例如輪詢和加權輪詢。

我們要保證使用者請求能夠均勻分佈到伺服器上面,同一個會話的請求保證在同一個伺服器上面處理,針對不同伺服器資源的優劣動態調整流量。

負載均衡器加入之後,由於其位於網際網路與應用伺服器之間,負責使用者流量的接入,因此可以對使用者流量進行監控,同時對訪問使用者的身份和許可權進行驗證。

資料庫讀寫分離

加入快取可以解決部分熱點資料的讀取,但快取資料的容量有限,那些非熱點的資料依舊會從資料庫中讀取。資料庫對於寫入和讀取的效能是不一樣的。

在寫入資料的時候,會造成鎖行或者鎖表,此時如果有其他寫入操作併發執行,會存在排隊現象。

而讀取操作比寫入操作更加快捷,並且可以透過索引、資料庫快取等方式實現。

因此,推出了資料庫讀寫分離的方案

此時設定了主從資料庫,主庫(master)主要用來寫入資料,然後透過同步 binlog 的方式,將更新的資料同步到從庫(slave)中。

對於應用伺服器而言,在寫資料的時候只需要訪問主庫,在讀資料的時候只用訪問從庫就好了。

利用資料庫讀寫分離的方式,將資料庫的讀/寫職責分離。利用讀資料效率較高的優勢,擴充套件更多的從庫,從而服務於讀取操作的使用者請求。畢竟在現實場景中,大多數操作都是讀取操作。

此外,從資料同步技術的角度來說,又可以分為同步複製技術、非同步複製技術和半同步複製技術。在資料庫讀寫分離帶來益處的同時,架構也需要考慮可靠性的問題。

例如,主庫如果掛掉,從庫如何接替主庫進行工作。主庫在恢復以後,是成為從庫還是繼續擔當主庫,以及如何同步資料的問題。

反向代理與 CDN

隨著網際網路的逐漸普及,人們對網路安全和使用者體驗的要求也越來越高。之前使用者都是透過客戶端直接訪問應用伺服器獲取服務,應用伺服器會暴露在網際網路中,容易遭到攻擊。

如果在應用伺服器與網際網路之間加上一個反向代理伺服器,它接收使用者的請求,然後再轉發到內網的應用伺服器,充當外網與內網之間的緩衝。

反向代理伺服器只是做請求的轉發,在它上面沒有執行任何應用,因此當有人攻擊它的時候,是不會影響到內網的應用伺服器的。

這無形中保護了應用伺服器,提高了安全性。同時,它也在網際網路與內網之間起到適配和網速轉換的作用。

例如,應用伺服器需要服務公網和教育網,但是兩個網路的網速不同,可以在應用伺服器與網際網路之間放上兩臺反向代理伺服器,一臺連線公網,另一臺連線教育網,遮蔽網路差異,服務於更多的使用者群體。

由於兩個網路訪問速度不同,因此會針對兩個網路分別設定共網代理伺服器和校園網代理伺服器,透過這種方式將位於不通網路的使用者請求接入到系統中。

聊完反向代理,再來說說 CDN,它的全稱是 Content Delivery Network,也就是內容分發網路。

如果把網際網路想象成一張大網的話,每個伺服器或者客戶端就是分散式在網中的一個節點。

節點之間的距離有遠有近,使用者請求會從一個節點跳轉到另外一個節點,最終跳轉到應用伺服器獲取資訊。

如果跳轉的次數越少,就能夠更快地獲取資訊,因此可以在離客戶端近的節點存放資訊。

這樣使用者透過客戶端,只需要較少的跳轉次數就能夠觸達資訊。由於這部分資訊更新頻率不高,推薦存放一些靜態資料,例如 JavaScript 檔案、靜態的 HTML、圖片檔案等。

這樣客戶端就可以從離自己最近的網路節點獲取資源,大大提高了使用者體驗和傳輸效率。

CDN 的加入明顯加快了使用者訪問應用伺服器的速度,同時也減輕了應用伺服器的壓力,原來必須直接訪問應用伺服器的請求,不用經過層層網路,而只用找到最近的網路節點就可以獲取資源。

但從請求資源的角度上來看,這種方式也有侷限性,它只能對靜態資源起作用,需要定時對 CDN 伺服器進行資源更新。反向代理和 CDN 的加入解決了安全性、可用性和高效能的問題。

分散式資料庫與分表分庫

經歷前面幾個階段以後,軟體的系統架構相對趨於穩定。隨著系統執行時間的增加,資料庫中累積的資料越來越多,同時系統還會記錄一些過程資料,例如操作資料和日誌資料,這些資料也會加重資料庫的負擔。

即便資料庫設定了索引和快取,但在海量資料查詢的時候還會捉襟見肘。如果說讀寫分離,是將資料庫從讀寫層面進行資源分配,那麼分散式資料庫就需要從業務和資料層面對資源進行分配。

①對於資料表來說

,當表中包含的記錄過多時,會將其分成多張表來儲存。

例如:有 1000 萬個會員記錄,就可以將其分成兩個 500 萬,分別放到兩個表中儲存。

也可以按照業務將表中的列進行分割,把表中的某些列放到其他表中儲存,然後透過外來鍵關聯到主表,被分割出去的列通常是不經常訪問的資料。

②對於資料庫來說

,每個資料庫能夠承受的最大連線數和連線池是有上限的。為了提高資料訪問效率,會根據業務需求對資料庫進行分割,讓不同的業務訪問不同的資料庫。當然,也可以將相同業務的不同資料放到不同的庫中儲存。

如果將這些資料庫資源分別放到不同的資料庫伺服器中,就是分散式資料庫設計了。

由於資料儲存在不同的表/庫中,甚至在不同的伺服器上面,在進行資料庫操作的時候會增加程式碼的複雜度。此時可以加入資料庫中介軟體來消除這些差異。

將資料拆分以後分別放在表 1 和表 2 中,兩張表所在的資料庫伺服器也各不相同,庫與庫之間還需要考慮資料同步的問題。

由於資料的分散部署,要從業務應用獲取資料就需要依靠資料庫中介軟體幫忙。

8:分散式資料庫與分表分庫

資料庫的分表分庫以及分散式設計,會帶來效能的提升,同時也增大了資料庫管理和訪問的難度。原來只用訪問一張表和一個庫,現在需要跨越多張表和多個庫。

從軟體程式設計的角度來看,有一些資料庫中介軟體提供了最佳實踐,例如 MyCat 和 Sharding JDBC。

此外,從資料庫伺服器管理的角度來看,需要監控伺服器的可用性。從資料治理的角度來看,需要考慮資料擴容和資料治理的問題。

業務拆分

當解決大資料量儲存問題以後,系統就能夠儲存更多的資料,這意味著能夠處理更多的業務。

業務量的增加,訪問數的上升,是任何一個軟體系統在任何時期都要面臨的嚴峻考驗。

透過前面幾個階段的學習,我們知道系統提升基本依靠空間換取時間,使用更多的資源和空間處理更多的使用者請求。

隨著業務的複雜度越來越高,以及高併發的來臨,一些大廠開始將業務系統進行切分,分開部署。

如果說前面的伺服器叢集模式是將同一個應用複製到不同的伺服器上,那麼業務拆分就是將一個應用拆成多個部署到不同的伺服器中。

此外,還可以對核心應用進行水平擴充套件,將其部署到多臺伺服器上。應用雖然做了拆分,但應用之間仍舊有關聯,存在應用之間的呼叫、通訊和協調問題。

由此也會引入佇列、服務註冊發現、訊息中心等中介軟體,它們可以協助系統管理分佈到不同伺服器、網路節點上的應用。

業務拆分以後會形成一個個應用服務,既有基於業務的服務,例如商品服務、訂單服務,也有基礎服務,例如訊息推送和許可權驗證。

這些應用服務連同資料庫伺服器分佈在不同的容器、伺服器、網路節點中,對它們的通訊、協調、管理和監控都是我們需要解決的問題。

分散式與微服務

近幾年,微服務是比較火的架構方式,它將業務應用進行更加精細化的切割,使之成為更加小的業務模組。

做到模組的高內聚低耦合,每個模組可以獨立存在,由獨立的團隊維護。每個模組內部可以採取特有的技術,而不用關心其他模組的技術實現。

模組透過容器的部署執行,模組之間透過介面和協議進行呼叫。任何一個模組都可以將自己公開給其他的模組呼叫。

同時可以將熱點模組進行水平擴充套件,增強系統的效能。當其中某一個模組出現問題時,又可以由其他相同的模組代替其工作,增強了可用性。

大致總結下來,微服務擁有以下特點,業務精細化拆分、自治性、技術異構性、高效能、高可用。

它像極了分散式架構,下面來看看它們的區別,如圖

從概念上理解,它們都做了“拆”的動作,但在下面這幾個方面存在區別:

①拆分目的不同

:分散式設計是為了解決單體應用資源有限的問題,在一個伺服器上無法支撐更高的使用者訪問,因此將一個應用拆解成不同的部分,然後將其部署到不同伺服器上,從而分擔高併發的壓力。

微服務是對服務元件進行精細化,目的是更好地解耦,讓服務之間透過組合完成高效能、高可用、可伸縮、可擴充套件。

②拆分方式不同

:分散式服務架構將系統按照業務和技術分類進行拆分,目的是讓拆分的服務負載原來單一服務的業務。

微服務則是在分散式的基礎上進行更細的拆分,它將服務拆成更小的模組,更加專業化,分工更加精細,並且每個小模組都可以獨立執行。

③部署方式不同

:分散式將服務拆分以後,通常會部署到不同的伺服器上。

而微服務也可以將不同的服務模組放到不同的伺服器上,同時它也可以在一個伺服器上部署多個微服務,或者同一個微服務的多個備份,並且多使用容器的方式部署。

雖然分散式與微服務有以上區別,但從實踐的角度來看,它們都是基於分散式架構的思想構建的。

微服務是分散式的進化版本,也是分散式的子集。它同樣會遇到服務拆分、服務通訊、協同、管理排程等問題。

總結

本文按照技術跟隨業務變化的思路,描述從單體架構到叢集,再到分散式架構以及微服務的發展階段,講述了每個軟體架構階段變化的特點,前後架構更替的原因和關係,說明了軟體架構發展會一直隨著業務發展的方向變化。遵循高效能,高可用,伸縮性,擴充套件性,安全性的架構目的。

By tony

自由軟體愛好者~喜歡不斷的思考各種問題,有新的事物都會想去學習嘗試 做實驗並熱衷研究 沒有所謂頂天的技術 只有謙虛及不斷的學習 精進專業,本站主要以分享系統及網路相關知識、資源而建立。 Github http://stnet253.github.io

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料