官术网_书友最值得收藏!

1.1 架構設計的演進過程

業務驅動著技術發展是亙古不變的道理。最開始的時候,業務量少、復雜度低,采取的技術也相對簡單,能夠基本滿足用戶對功能的需求。隨著 IT 信息化的普及,更多交易被放到了網絡上,增加的信息量和頻繁的業務訪問就變成了需要解決的問題。因此,逐漸產生了緩存、集群等技術手段,同時對業務擴展性和伸縮性的要求也變得越來越高。高并發、高可用、可伸縮、可擴展、夠安全一直都是架構設計所追求的目標。下面我們來看一下架構設計經歷了哪些階段,以及每個階段分別解決了哪些問題,又引出了哪些新問題。

1.1.1 應用與數據一體模式

最早的業務應用以網站、OA 等為主,訪問人數有限,單臺服務器就能輕松應付,利用 LAMP(Linux、Apache、MySQL、PHP)技術就可以迅速搞定,并且這幾種工具都是開源的。在很長一段時間內,有各種針對這種應用模式的開源代碼可以使用,但這種模式基本上沒有高并發的特性,可用性也很差。有些服務器采用的是托管模式,上面安裝著不同的業務應用,一旦服務器出現問題,所有應用就都罷工了,不過其開發和部署成本相對較低,適合剛剛起步的應用服務。圖 1-1 描述了單個應用和數據庫運行在單臺服務器上的模式,我們稱這種模式為應用與數據一體模式。

圖 1-1 應用與數據一體模式

1.1.2 應用與數據分離模式

隨著業務的發展,用戶數量和請求數量逐漸上升,服務器的性能便出現了問題。一個比較簡單的解決方案是增加資源,將業務應用和數據分開存儲,其架構圖如圖 1-2 所示。其中,應用服務器由于需要處理大量的業務請求,因此對 CPU 和內存有一定要求;而數據服務器因為需要對數據進行存儲和索引等 IO 操作,所以更多地會考慮磁盤的轉速和內存。這種分離模式解決了性能問題,相應地,也需要擴展更多硬件資源讓兩種服務器各司其職,使系統可以處理更多的用戶請求。雖然業務應用本身沒有進行切分,業務應用內部的業務模塊依舊存在耦合,但硬件層面的分離在可用性上比一體式設計要好很多。

圖 1-2 應用與數據分離模式

1.1.3 緩存與性能的提升

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

?客戶端瀏覽器緩存:當用戶通過瀏覽器請求應用服務器的時候,會發起 HTTP 請求。如果將每次 HTTP 請求都緩存下來,就可以極大地減小應用服務器的壓力。

?應用服務器本地緩存:這種緩存使用的是進程內緩存,又叫托管堆緩存。以 Java 為例,這部分緩存存放在 JVM 的托管堆上面,會受到托管堆回收算法的影響。由于它運行在內存中,對數據的響應速度很快,因此通常用于存放熱點數據。當進程內緩存沒有命中時,會到緩存服務器中獲取信息,如果還是沒有命中,才會去數據庫中獲取。

?緩存服務器緩存:這種緩存相對于應用服務器本地緩存來說,就是進程外緩存,既可以和應用服務部署在同一服務器上,也可以部署在不同的服務器上。一般來說,為了方便管理和合理利用資源,會將其部署在專門的緩存服務器上。由于緩存會占用內存空間,因此這類服務器往往會配置比較大的內存。

圖 1-3 緩存技術的加入

圖 1-3 描述了緩存的請求次序,先訪問客戶端瀏覽器緩存,然后是進程內的本地緩存,之后是緩存服務器,最后才是數據庫。只要在其中任意一個階段獲取到了緩存信息,就不會繼續往下訪問了,否則會一直按照這個次序獲取緩存信息,直到訪問數據庫。

用戶請求訪問數據的順序為客戶端瀏覽器緩存→應用服務器本地緩存→緩存服務器緩存。如果按照以上次序還沒有命中數據,才會訪問數據庫獲取數據。

加入緩存技術后,系統性能得到了提高。這是因為緩存位于內存中,而內存的讀取速度要比磁盤快得多,能夠很快響應用戶請求。特別針對一些熱點數據,優勢尤為明顯。同時,在可用性方面也有明顯改善,即使數據服務器出現短時間的故障,在緩存服務器中保存的熱點數據或者核心數據依然可以滿足用戶暫時的訪問。當然,后面會針對可用性進行優化。

1.1.4 服務器集群處理并發

經過前面三個階段的演進,系統對用戶的請求量有了很好的支持。實際上,這些都是在逐步提高系統的性能和可用性,這一核心問題會一直貫穿于整個系統架構的演進過程中??呻S著用戶請求量的增加,另外一個問題又出現了,那就是并發。把這兩個字拆開了來看:并,可以理解為“一起并行”,有同時的意思;發,可以理解為“發出調用”,也就是發出請求的意思。合起來,并發就是指多個用戶同時請求應用服務器。如果說原來的系統面對的只是大數據量,那么現在就需要面對多個用戶同時請求。此時若還是按照上一個階段的架構圖推導,那么單個應用服務器已經無法滿足高并發的要求了。此時,服務器集群加入了戰場,其架構圖如圖 1-4 所示。服務器集群說白了,就是多臺服務器扎堆的意思,用更多服務器來分擔單臺服務器的負載壓力,提高性能和可用性。再說白一點,就是提高單位時間內服務處理請求的數量。原來是一臺服務器處理多個用戶的請求,現在是一堆服務器處理,就好像銀行柜臺一樣,通過增加柜員的人數來服務更多的客戶。

圖 1-4 服務器集群的加入

這次的架構演進與上次相比,增加了應用服務器的個數,用多臺應用服務器形成服務器集群,單臺應用服務器中部署的應用服務并沒有改變,在用戶請求與服務器之間加入了負載均衡器,以便將用戶請求路由到對應的服務器中。這次解決的系統瓶頸是如何處理用戶的高并發請求,因此對數據庫和緩存都沒有做更改,僅通過增加服務器的數量便能緩解并發請求的壓力。服務器集群通過多臺服務器分擔原來一臺服務器需要處理的請求,在多臺服務器上同時運行一套系統,同時處理大量并發的用戶請求,有點三個臭皮匠頂個諸葛亮的意思,因此對集群中單臺服務器的硬件要求也隨之降低。此時需要注意負載均衡器采用的均衡算法(例如輪詢和加權輪詢)要能保證用戶請求均勻地分布到多臺服務器上、屬于同一個會話的所有請求在同一個服務器上處理,以及針對不同服務器資源的優劣能夠動態調整流量。加入負載均衡器之后,由于其位于互聯網與應用服務器之間,負責用戶流量的接入,因此可以對用戶流量進行監控,同時對提出訪問請求的用戶的身份和權限進行驗證。

1.1.5 數據庫讀寫分離

加入緩存可以解決部分熱點數據的讀取問題,但緩存的容量畢竟有限,那些非熱點的數據依然要從數據庫中讀取。數據庫對于寫入和讀取操作的性能是不一樣的。在寫入數據時,會造成鎖行或者鎖表,此時如果有其他寫入操作并發執行,就會出現排隊現象。而讀取操作不僅比寫入操作更加快捷,并且可以通過索引、數據庫緩存等方式實現。因此,推出了數據庫讀寫分離的方案,其架構圖如圖 1-5 所示。這種模式設置了主從數據庫,主庫(master)主要用來寫入數據,然后通過同步 binlog 的方式,將更新的數據同步到從庫(slave)中。對于應用服務器而言,在寫數據時只需要訪問主庫,在讀數據時只用訪問從庫就好了。

圖 1-5 數據庫讀寫分離

數據庫讀寫分離的方式將數據庫的讀、寫職責分離開來,利用讀數據效率較高的優勢,擴展更多的從庫,從而服務于請求讀取操作的用戶。畢竟在現實場景中,大多數操作是讀取操作。此外,數據同步技術可以分為同步復制技術、異步復制技術和半同步復制技術,這些技術的原理會在第 6 章中為大家介紹。體會到數據庫讀寫分離帶來的益處的同時,架構設計也需要考慮可靠性的問題。例如,如果主庫掛掉,從庫如何接替主庫進行工作;之后主庫恢復了,是成為從庫還是繼續擔任主庫,以及主從庫如何同步數據。這些問題的解決方案在第 6 章會講述。

1.1.6 反向代理和 CDN

隨著互聯網的逐漸普及,人們對網絡安全和用戶體驗的要求也越來越高。之前用戶都是通過客戶端直接訪問應用服務器獲取服務,這使得應用服務器暴露在互聯網中,容易遭到攻擊。如果在應用服務器與互聯網之間加上一個反向代理服務器,由此服務器來接收用戶的請求,然后再將請求轉發到內網的應用服務器,相當于充當外網與內網之間的緩沖,就可以解決之前的問題。反向代理服務器只對請求進行轉發,自身不會運行任何應用,因此當有人攻擊它的時候,是不會影響到內網的應用服務器的,這在無形中保護了應用服務器,提高了安全性。同時,反向代理服務器也在互聯網與內網之間起適配和網速轉換的作用。例如,應用服務器需要服務于公網和教育網,但是這兩個網絡的網速不同,那么就可以在應用服務器與互聯網之間放兩臺反向代理服務器,一臺連接公網,另一臺連接教育網,用于屏蔽網絡差異,服務于更多的用戶群體。圖 1-6 中的公網客戶端和校園網客戶端分別來自公網與校園網兩個不同的網絡,由于兩者訪問速度不同,因此會分別設置公網反向代理服務器和校園網反向代理服務器,通過這種方式將位于不通網絡的用戶請求接入到系統中。

圖 1-6 加入反向代理服務器

聊完反向代理,再來說 CDN,它的全稱是 Content Delivery Network,也就是內容分發網絡。如果把互聯網想象成一張大網,那么每臺服務器或者每個客戶端就是分布在這張大網中的節點。節點之間的距離有遠有近,用戶請求會從一個節點跳轉到另外一個節點,最終跳轉到應用服務器獲取信息。跳轉的次數越少,越能夠快速地獲取信息,因此可以在離客戶端近的節點中存放信息。這樣用戶通過客戶端,只需要跳轉較少的次數就能夠觸達信息。由于這部分信息更新頻率不高,因此推薦存放一些靜態數據,例如 JavaScript 文件、靜態的 HTML、圖片文件等。這樣客戶端就可以從離自己最近的網絡節點獲取資源,大大提升了用戶體驗和傳輸效率。加入 CDN 后的架構圖如圖 1-7 所示。

圖 1-7 加入 CDN

CDN 的加入明顯加快了用戶訪問應用服務器的速度,同時減輕了應用服務器的壓力,原來必須直接訪問應用服務器的請求,現在不需要經過層層網絡,只要找到最近的網絡節點就可以獲取資源。但從請求資源的角度來看,這種方式也有局限性,即它只對靜態資源起作用,而且需要定時對 CDN 服務器進行資源更新。反向代理和 CDN 的加入解決了安全性、可用性和高性能的問題。

1.1.7 分布式數據庫與分表分庫

經歷了前面幾個階段的演進后,軟件的系統架構已經趨于穩定。可是隨著系統運行時間的增加,數據庫中累積的數據越來越多,同時系統還會記錄一些過程數據,例如操作數據和日志數據,這些數據也會加重數據庫的負擔。即便數據庫設置了索引和緩存,但在進行海量數據查詢時還是會表現得捉襟見肘。如果說讀寫分離是對數據庫資源從讀寫層面進行分配,那么分布式數據庫就需要從業務和數據層面對數據庫進行分配。

?對于數據表來說,當表中包含的記錄過多時,可將其分成多張表來存儲。例如,有 1000 萬個會員記錄,既可以將其分成兩個 500 萬,分別放到兩張表中存儲,也可以按照業務對表中的列進行分割,把表中的某些列放到其他表中存儲,然后通過外鍵關聯到主表。注意被分割出去的列通常是不經常訪問的數據。

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

如果將數據庫資源分別放到不同的數據庫服務器中,就是分布式數據庫設計。由于數據存儲在不同的表/庫中,甚至在不同的服務器上面,因此在進行數據庫操作的時候會增加代碼的復雜度。此時可以加入數據庫中間件來實現數據同步,從而消除不同存儲載體間的差異。架構如圖 1-8 所示,將數據拆分以后分別放在表 1 和表 2 中,兩張表所在的數據庫服務器也不相同,庫與庫之間還需要考慮數據同步的問題。因為數據的分散部署,所以從業務應用獲取數據時需要依靠數據庫中間件的幫忙。

圖 1-8 分布式數據庫與分表分庫

數據庫的分布式設計以及分表分庫,會給系統帶來性能的提升,同時也增大了數據庫管理和訪問的難度。原來只需訪問一張表和一個庫就可以獲取數據,現在需要跨越多張表和多個庫。

從軟件編程的角度來看,有一些數據庫中間件提供了最佳實踐,例如 MyCat 和 Sharding JDBC。此外,從數據庫服務器管理的角度來看,需要監控服務器的可用性。從數據治理的角度來看,需要考慮數據擴容和數據治理的問題。

1.1.8 業務拆分

解決了大數據量存儲問題以后,系統就能夠存儲更多的數據,這意味著能夠處理更多的業務。業務量的增加、訪問數的上升,是任何一個軟件系統在任何時期都要面臨的嚴峻考驗。通過對前面幾個階段的學習,我們知道系統提升依靠的基本都是以空間換取時間,使用更多的資源和空間處理更多的用戶請求。隨著業務的復雜度越來越高,以及高并發的來臨,一些大廠開始對業務應用系統進行拆分,將應用分開部署,此時的架構圖如圖 1-9 所示。如果說前面的服務器集群模式是將同一個應用復制到不同的服務器上,那么業務拆分就是將一個應用拆成多個部署到不同的服務器中。此外,還有的是對核心應用進行水平擴展,將其部署到多臺服務器上。應用雖然做了拆分,但應用之間仍舊有關聯,存在相互之間的調用、通信和協調問題。由此引入了隊列、服務注冊發現、消息中心等中間件,這些中間件可以協助系統管理分布到不同服務器、網絡節點上的應用。

圖 1-9 業務拆分

業務拆分以后會形成一個個應用服務,既有基于業務的服務,例如商品服務、訂單服務,也有基礎服務,例如消息推送和權限驗證。這些應用服務連同數據庫服務器分布在不同的容器、服務器、網絡節點中,它們之間的通信、協調、管理和監控都是我們需要解決的問題。

1.1.9 分布式與微服務

近幾年,微服務是一種比較火的架構方式,它對業務應用進行了更加精細化的切割,使之成為更小的業務模塊,能夠做到模塊間的高內聚低耦合,每個模塊都可以獨立存在,并由獨立的團隊維護。每個模塊內部可以采取特有的技術,而不用關心其他模塊的技術實現。模塊通過容器的部署運行,各模塊之間通過接口和協議實現調用??梢詫⑷魏我粋€模塊設為公開,以供其他模塊調用,也可以熱點模塊進行水平擴展,增強系統的整體性能,這樣當其中某一個模塊出現問題時,就能由其他相同的模塊代替其工作,增強了可用性。

大致總結下來,微服務擁有以下特點:業務精細化拆分、自治性、技術異構性、高性能、高可用。它像極了分布式架構,從概念上理解,二者都做了“拆”的動作,但在下面這幾個方面存在區別,直觀展示見圖 1-10。

?拆分目的不同:提出分布式設計是為了解決單體應用資源有限的問題,一臺服務器無法支撐更多的用戶訪問,因此將一個應用拆解成不同的部分,然后分別部署到不同服務器上,從而分擔高并發的壓力。微服務是對服務組件進行精細化,目的是更好地解耦,讓服務之間通過組合實現高性能、高可用、可伸縮、可擴展。

?拆分方式不同:分布式服務架構將系統按照業務和技術分類進行拆分,目的是讓拆分后的服務負載原來單一服務的業務。微服務則是在分布式的基礎上進行更細的拆分,它將服務拆成更小的模塊,不僅更專業化,分工也更為精細,并且每個小模塊都能獨立運行。

?部署方式不同:分布式架構將服務拆分以后,通常會把拆分后的各部分部署到不同服務器上。而微服務既可以將不同的服務模塊部署到不同服務器上,也可以在一臺服務器上部署多個微服務或者同一個微服務的多個備份,并且多使用容器的方式部署。

圖 1-10 分布式與微服務的區別

雖然分布式與微服務具有以上區別,但從實踐的角度來看,它們都是基于分布式架構的思想構建的??梢哉f微服務是分布式的進化版本,也是分布式的子集,因此它同樣會遇到服務拆分、服務通信、協同、管理調度等問題,這也是我在后面要給大家講解的內容。

主站蜘蛛池模板: 水城县| 肇庆市| 清流县| 新丰县| 镶黄旗| 房产| 会宁县| 台北市| 如皋市| 三河市| 盐山县| 汉沽区| 鱼台县| 田东县| 郸城县| 屏南县| 阿勒泰市| 肇东市| 聂荣县| 嘉鱼县| 迭部县| 栖霞市| 新和县| 岳西县| 新乐市| 鄂尔多斯市| 樟树市| 梁平县| 通海县| 石家庄市| 泗阳县| 望城县| 射阳县| 博罗县| 麦盖提县| 天全县| 珲春市| 成安县| 射洪县| 中卫市| 凌云县|