濃縮精華的架構演進過程,經驗總結,值得收藏!

架構設計的演進過程

業務驅動技術的發展是亙古不變的道理。最開始的時候,業務量少,業務複雜度低,採起的技術也相對簡單,基本知足用戶對功能的需求。隨着IT信息化的普及,更多的交易放到了網絡上,信息量增長和訪問次數頻繁就是要解決的問題了。所以,逐漸加入了緩存、集羣等技術手段。同時對業務的擴展性和伸縮性的要求也愈來愈高。高併發、高可用、可伸縮、可擴展、夠安全的軟件架構一直是架構設計追求的目標。今天咱們來看一下架構設計經歷了哪些階段,每一個階段都解決了哪些問題,又引出了哪些新問題。主要是引發你們的思考,在不一樣的業務發展階段採起合適技術手段,用變化擁抱變化是IT人追求的目標。算法

應用與數據一體模式

最先的業務應用以網站、OA等爲主,訪問的人數有限,單臺服務器就可以應付。一般,將應用程序和數據庫部署到一臺服務器上面,如圖1-1所示。在這一階段,咱們利用LAMP(Linux Apache MySQL PHP)技術就能夠迅速搞定,而且這些工具都是開源的。很長一段時間內,有各類針對這種應用模式的開源代碼可使用。這種模式基本上沒有高併發的要求,可用性也不好。有的服務器採用託管模式,上面就安裝了不一樣的業務應用,一旦服務器出現問題,全部的應用就罷工了。不過其開發和部署成本相對較低,適合剛剛起步的應用服務。圖1 就描述了單個應用和數據庫運行在單臺服務器的模式,咱們稱這種模式爲應用與數據一體模式。
濃縮精華的架構演進過程,經驗總結,值得收藏!
圖 1 應用與數據一體模式數據庫

應用與數據分離模式

隨着業務的發展,用戶數和請求數逐漸上升,服務器的性能出現了問題。其中比較簡單的解決方案就是增長資源,將業務應用和數據存儲分開,其架構圖如圖2所示。其中,應用服務器須要處理大量的業務請求,對CPU和內存有必定要求;而數據庫服務器須要對數據進行存儲和索引等IO操做,對磁盤的轉速和內存會考慮更多。這樣的分離解決了性能的問題,咱們須要擴展更多的硬件資源讓其各司其職,使系統能夠處理更多的用戶請求。雖然業務上依舊存在耦和,但硬件層面的分離在可用性上比一體式設計要好不少。
濃縮精華的架構演進過程,經驗總結,值得收藏!
圖2 應用與數據分離模式編程

緩存的加入

隨着信息化系統的發展和使用互聯網人數的增多,業務量、用戶量、數據量都在增加。咱們同時發現,用戶會對某些數據的請求量特別大,例如新聞、商品信息和熱門消息。以前這些信息的獲取方式是依靠數據庫,所以受到數據庫IO性能的影響。此時數據庫成爲了整個系統的瓶頸。若是再增長服務器的數量,恐怕也很難解決,因而緩存技術就登場了,其架構圖如圖3所示。這裏提到的緩存技術分爲客戶端瀏覽器緩存、應用服務器本地緩存和緩存服務器緩存。瀏覽器

  • 客戶端瀏覽器緩存:當用戶經過瀏覽器請求服務器的時候,會發起HTTP請求。若是對每次HTTP請求進行緩存,那麼能夠減小應用服務器的壓力。
  • 應用服務器本地緩存:它使用的是進程內緩存,又叫託管堆緩存。以Java爲例,這部分緩存放在JVM的託管堆上面,同時會受到託管堆回收算法的影響。因爲它運行在內存中,對數據的響應速度很快,一般咱們會把熱點數據放在這裏。在進程內緩存沒有命中的時候,會到緩存服務器中獲取信息,若是仍是沒有命中,纔會去數據庫中獲取。
  • 緩存服務器緩存:它相對於應用服務器本地緩存來講,就是進程外緩存,既能夠和應用服務部署在同一服務器,也能夠部署到不一樣的服務器。通常來講,爲了方便管理和合理利用資源,會將其部署到專門的緩存服務器上面。因爲緩存會佔用內存空間,所以這類服務器會配置比較大的內存。
    圖3 描述了緩存請求的次序,先訪問客戶端緩存,以後是進程內的本地緩存,接下來是緩存服務器,最後纔是數據。若是在任意一層獲取了緩存信息,就再也不往下訪問了,不然會一直按照這個次序獲取緩存信息,直到數據庫。
    濃縮精華的架構演進過程,經驗總結,值得收藏!
    圖3 緩存的加入
    用戶請求訪問數據的順序爲客戶端瀏覽器緩存→應用服務器本地緩存→緩存服務器緩存。若是按照以上次序尚未命中數據,纔會訪問數據庫獲取數據。
    加入緩存的設計,提升了系統的性能。因爲緩存放在內存中,而內存的讀取速度比磁盤要快得多,可以很快響應用戶請求。特別針對一些熱點數據,優點尤其明顯。同時,在可用性方面也有明顯的改善。即便數據庫服務器出現短期的故障,緩存服務器中保存的熱點或者核心數據依舊能夠知足用戶暫時的訪問。固然,後面還會對可用性進行優化。

    服務器集羣的加入

    通過前面三個階段的演進,系統對用戶的請求量有了很好的支持。實際上,這都是在解決高性能和可用性的問題,這一核心問題會一直貫穿整個系統架構的演進過程當中。隨着用戶請求量的增長,另一個問題又出現了,那就是併發。把這兩個字拆開了來看:並,理解爲「一塊兒並行「,有同時的意思;發,理解爲「發出調用」,也就是請求的意思。合起來就是多個用戶同時請求應用服務器。若是說原來的系統面對的僅僅只是大數據量的話,那麼如今就須要面對多用戶同時請求。若是仍是按照上一個階段的架構圖推導,單個應用服務器已經沒法知足高併發的要求了。此時,服務器集羣就加入戰場了,其架構圖如圖4所示。服務器集羣也就是多臺服務器扎堆的意思,用更多的服務器來分擔單臺服務器的負載壓力,提升性能和可用性。再說白一點,就是提升單位時間內服務處理請求的數量。原來是一個服務器處理,如今是一堆服務器來處理。就好像銀行櫃檯同樣,增長櫃員的人數來服務更多的人。
    濃縮精華的架構演進過程,經驗總結,值得收藏!
    圖4服務器集羣的加入
    此次架構演進與上次相比,增長了應用服務器的個數,用多臺應用服務器造成集羣。應用服務器中所部署的應用服務沒有改變,在用戶請求與服務器之間加入了負載均衡器,幫助用戶請求路由到對應的服務器中。增長服務器的舉動代表,系統的瓶頸是在處理用戶併發請求上。針對數據庫和緩存都沒有作更改,這樣僅僅經過增長服務器數量就可以緩解請求的壓力。服務器集羣會經過多臺服務器來分擔原來一臺服務器須要處理的請求,在多臺服務器上同時運行一套系統,所以能夠同時處理大量併發的用戶請求。有點三個臭皮匠頂個諸葛亮的意思,所以對集羣中單個服務器的硬件要求也會下降。此時須要注意負載均衡均衡的算法,例如輪詢和加權輪詢。咱們要保證用戶請求可以均勻分佈到服務器上面,同一個會話的請求保證在同一個服務器上面處理,針對不一樣服務器資源的優劣動態調整流量。負載均衡器加入以後,因爲其位於互聯網與應用服務器之間,負責用戶流量的接入,所以能夠對用戶流量進行監控,同時對訪問用戶的身份和權限進行驗證。緩存

    數據庫讀寫分離

    加入緩存能夠解決部分熱點數據的讀取,但緩存數據的容量有限,那些非熱點的數據依舊會從數據庫中讀取。數據庫對於寫入和讀取的性能是不同的。在寫入數據的時候,會形成鎖行或者鎖表,此時若是有其餘寫入操做併發執行,會存在排隊現象。而讀取操做比寫入操做更加快捷,而且能夠經過索引、數據庫緩存等方式實現。所以,推出了數據庫讀寫分離的方案,其架構圖如圖5所示。此時設置了主從數據庫,主庫(master)主要用來寫入數據,而後經過同步binlog的方式,將更新的數據同步到從庫(slave)中。對於應用服務器而言,在寫數據的時候只須要訪問主庫,在讀數據的時候只用訪問從庫就行了。
    濃縮精華的架構演進過程,經驗總結,值得收藏!
    圖5 數據庫讀寫分離
    利用數據庫讀寫分離的方式,將數據庫的讀/寫職責分離。利用讀數據效率較高的優點,擴展更多的從庫,從而服務於讀取操做的用戶請求。畢竟在現實場景中,大多數操做都是讀取操做。此外,從數據同步技術的角度來講,又能夠分爲同步複製技術、異步複製技術和半同步複製技術。在數據庫讀寫分離帶來益處的同時,架構也須要考慮可靠性的問題。例如,主庫若是掛掉,從庫如何接替主庫進行工做。主庫在恢復之後,是成爲從庫仍是繼續擔當主庫,以及如何同步數據的問題。安全

    反向代理與CDN

    隨着互聯網的逐漸普及,人們對網絡安全和用戶體驗的要求也愈來愈高。以前用戶都是經過客戶端直接訪問應用服務器獲取服務,應用服務器會暴露在互聯網中,容易遭到***。若是在應用服務器與互聯網之間加上一個反向代理服務器,它接收用戶的請求,而後再轉發到內網的應用服務器,充當外網與內網之間的緩衝。反向代理服務器只是作請求的轉發,在它上面沒有運行任何應用,所以當有人***它的時候,是不會影響到內網的應用服務器的。這無形中保護了應用服務器,提升了安全性。同時,它也在互聯網與內網之間起到適配和網速轉換的做用。例如,應用服務器須要服務公網和教育網,可是兩個網絡的網速不一樣,能夠在應用服務器與互聯網之間放上兩臺反向代理服務器,一臺鏈接公網,另外一臺鏈接教育網,屏蔽網絡差別,服務於更多的用戶羣體。如圖6 公網客戶端和校園網客戶端分別來自公網與校園網兩個不一樣的網絡,因爲兩個網絡訪問速度不一樣,所以會針對兩個網絡分別設置共網代理服務器和校園網代理服務器,經過這種方式將位於不通網絡的用戶請求接入到系統中。
    濃縮精華的架構演進過程,經驗總結,值得收藏!
    圖6加入反向代理服務器
    聊完反向代理,再來講說CDN,它的全稱是Content Delivery Network,也就是內容分發網絡。若是把互聯網想象成一張大網的話,每一個服務器或者客戶端就是分佈式在網中的一個節點。節點之間的距離有遠有近,用戶請求會從一個節點跳轉到另一個節點,最終跳轉到應用服務器獲取信息。若是跳轉的次數越少,就可以更快地獲取信息,所以能夠在離客戶端近的節點存放信息。這樣用戶經過客戶端,只須要較少的跳轉次數就可以觸達信息。因爲這部分信息更新頻率不高,推薦存放一些靜態數據,例如JavaScript文件、靜態的HTML、圖片文件等。這樣客戶端就能夠從離本身最近的網絡節點獲取資源,大大提升了用戶體驗和傳輸效率。加入CDN後的架構圖如圖7所示。
    濃縮精華的架構演進過程,經驗總結,值得收藏!
    圖7 加入CDN
    CDN的加入明顯加快了用戶訪問應用服務器的速度,同時也減輕了應用服務器的壓力,原來必須直接訪問應用服務器的請求,不用通過層層網絡,而只用找到最近的網絡節點就能夠獲取資源。但從請求資源的角度上來看,這種方式也有侷限性,它只能對靜態資源起做用,須要定時對CDN服務器進行資源更新。反向代理和CDN的加入解決了安全性、可用性和高性能的問題。服務器

    分佈式數據庫與分表分庫

    經歷前面幾個階段之後,軟件的系統架構相對趨於穩定。隨着系統運行時間的增長,數據庫中累積的數據愈來愈多,同時系統還會記錄一些過程數據,例如操做數據和日誌數據,這些數據也會加劇數據庫的負擔。即使數據庫設置了索引和緩存,但在海量數據查詢的時候還會捉襟見肘。若是說讀寫分離,是將數據庫從讀寫層面進行資源分配,那麼分佈式數據庫就須要從業務和數據層面對資源進行分配。網絡

  • 對於數據表來講,當表中包含的記錄過多時,會將其分紅多張表來存儲。例如:有1000萬個會員記錄,就能夠將其分紅兩個500萬,分別放到兩個表中存儲。也能夠按照業務將表中的列進行分割,把表中的某些列放到其餘表中存儲,而後經過外鍵關聯到主表,被分割出去的列一般是不常常訪問的數據。
  • 對於數據庫來講,每一個數據庫可以承受的最大鏈接數和鏈接池是有上限的。爲了提升數據訪問效率,會根據業務需求對數據庫進行分割,讓不一樣的業務訪問不一樣的數據庫。固然,也能夠將相同業務的不一樣數據放到不一樣的庫中存儲。
    若是將這些數據庫資源分別放到不一樣的數據庫服務器中,就是分佈式數據庫設計了。因爲數據存儲在不一樣的表/庫中,甚至在不一樣的服務器上面,在進行數據庫操做的時候會增長代碼的複雜度。此時能夠加入數據庫中間件來消除這些差別。架構如圖8所示,將數據拆分之後分別放在表1和表2 中,兩張表所在的數據庫服務器也各不相同,庫與庫之間還須要考慮數據同步的問題。因爲數據的分散部署,要從業務應用獲取數據就須要依靠數據庫中間件幫忙。
    濃縮精華的架構演進過程,經驗總結,值得收藏!
    圖8 分佈式數據庫與分表分庫
    數據庫的分表分庫以及分佈式設計,會帶來性能的提高,同時也增大了數據庫管理和訪問的難度。原來只用訪問一張表和一個庫,如今須要跨越多張表和多個庫。
    從軟件編程的角度來看,有一些數據庫中間件提供了最佳實踐,例如MyCat和Sharding JDBC。此外,從數據庫服務器管理的角度來看,須要監控服務器的可用性。從數據治理的角度來看,須要考慮數據擴容和數據治理的問題。

    業務拆分

    當解決大數據量存儲問題之後,系統就可以存儲更多的數據,這意味着可以處理更多的業務。業務量的增長,訪問數的上升,是任何一個軟件系統在任什麼時候期都要面臨的嚴峻考驗。經過前面幾個階段的學習,咱們知道系統提高基本依靠空間換取時間,使用更多的資源和空間處理更多的用戶請求。隨着業務的複雜度愈來愈高,以及高併發的來臨,一些大廠開始將業務系統進行切分,分開部署,此時的架構圖如圖10所示。若是說前面的服務器集羣模式是將同一個應用複製到不一樣的服務器上,那麼業務拆分就是將一個應用拆成多個部署到不一樣的服務器中。此外,還能夠對核心應用進行水平擴展,將其部署到多臺服務器上。應用雖然作了拆分,但應用之間仍舊有關聯,存在應用之間的調用、通訊和協調問題。由此也會引入隊列、服務註冊發現、消息中心等中間件,它們能夠協助系統管理分佈到不一樣服務器、網絡節點上的應用。
    濃縮精華的架構演進過程,經驗總結,值得收藏!
    圖9業務拆分
    業務拆分之後會造成一個個應用服務,既有基於業務的服務,例如商品服務、訂單服務,也有基礎服務,例如消息推送和權限驗證。這些應用服務連同數據庫服務器分佈在不一樣的容器、服務器、網絡節點中,對它們的通訊、協調、管理和監控都是咱們須要解決的問題。架構

    分佈式與微服務

    近幾年,微服務是比較火的架構方式,它將業務應用進行更加精細化的切割,使之成爲更加小的業務模塊。作到模塊的高內聚低耦合,每一個模塊能夠獨立存在,由獨立的團隊維護。每一個模塊內部能夠採起特有的技術,而不用關心其餘模塊的技術實現。模塊經過容器的部署運行,模塊之間經過接口和協議進行調用。任何一個模塊均可以將本身公開給其餘的模塊調用。同時能夠將熱點模塊進行水平擴展,加強系統的性能。當其中某一個模塊出現問題時,又能夠由其餘相同的模塊代替其工做,加強了可用性。
    大體總結下來,微服務擁有如下特色,業務精細化拆分、自治性、技術異構性、高性能、高可用。它像極了分佈式架構,下面來看看它們的區別,如圖10所示。
    從概念上理解,它們都作了「拆」的動做,但在下面這幾個方面存在區別。併發

  • 拆分目的不一樣:分佈式設計是爲了解決單體應用資源有限的問題,在一個服務器上沒法支撐更高的用戶訪問,所以將一個應用拆解成不一樣的部分,而後將其部署到不一樣服務器上,從而分擔高併發的壓力。微服務是對服務組件進行精細化,目的是更好地解耦,讓服務之間經過組合完成高性能、高可用、可伸縮、可擴展。
  • 拆分方式不一樣:分佈式服務架構將系統按照業務和技術分類進行拆分,目的是讓拆分的服務負載原來單一服務的業務。微服務則是在分佈式的基礎上進行更細的拆分,它將服務拆成更小的模塊,更加專業化,分工更加精細,而且每一個小模塊均可以獨立運行。
  • 部署方式不一樣:分佈式將服務拆分之後,一般會部署到不一樣的服務器上。而微服務也能夠將不一樣的服務模塊放到不一樣的服務器上,同時它也能夠在一個服務器上部署多個微服務,或者同一個微服務的多個備份,而且多使用容器的方式部署。
    濃縮精華的架構演進過程,經驗總結,值得收藏!
    圖10 分佈式與微服務的區別
    雖然分佈式與微服務有以上區別,但從實踐的角度來看,它們都是基於分佈式架構的思想構建的。微服務是分佈式的進化版本,也是分佈式的子集。它一樣會遇到服務拆分、服務通訊、協同、管理調度等問題。

    總結

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

相關文章
相關標籤/搜索