歡迎光臨
每天分享高質量文章

標準Web系統的架構分層

來自:JAVA入門中

連結:https://blog.csdn.net/yinwenjie/article/details/46480485

1、架構體系分層圖


在上圖中我們描述了Web系統架構中的組成部分。並且給出了每一層常用的技術元件/服務實現。需要註意以下幾點:


  • 系統架構是靈活的,根據需求的不同,不一定每一層的技術都需要使用。例如:一些簡單的CRM系統可能在產品初期並不需要K-V作為快取;一些系統訪問量不大,並且可能只有一臺業務伺服器存在,所以不需要運用負載均衡層。

  • 業務系統間通訊層並沒有加入傳統的HTTP請求方式。這是因為HTTP請求-響應的延遲比較高,並且有很多次和正式請求無關的通訊(這在下麵的內容中會詳細講到)。所以,傳統的HTTP請求方式並不適合在兩個高負載系統之間使用,其更多的應用場景是各種客戶端(WEB、IOS、Android等)->伺服器端的請求呼叫。

  • 我們把業務編碼中常使用的快取系統歸入到資料儲存層,是因為類似於Redis這樣的K-V儲存系統,從本質上講是一種鍵值資料庫。為什麼Redis會很快以至於可以作為快取使用,我將在隨後的文章中進行詳細的描述。

  • 還有一點需要註意的是,上面架構圖中的每層之間實際上不存在絕對的聯絡(例如負載層一定會把請求轉送的業務層,這樣的必然性是不存在的),在通常情況下各層是可以跨越訪問的。舉例說明:如果HTTP訪問的是一張圖片資源,負載層不會把請求送到業務層,而是直接到部署的分散式檔案系統上尋找圖片資源並傳回。再比如運用LVS做Mysql負載時,負載層是直接和資料儲存層進行合作。


2、負載分配層

實際上負載均衡的概念很廣泛,所述的過程是將來源於外部的處理壓力透過某種規律/手段分攤到內部各個處理節點上。在日常生活中我們隨時隨地在和負載技術打交道,例如:上下班高峰期的車流量引導、民航空管局的航空流量管制、銀行櫃臺的叫號系統。

這裡我們所說的負載分配層,是單指利用軟體實現的計算機系統上的狹義負載均衡。一個大型(日PV一億+)、中型(日PV一千萬+)Web業務系統,是不可能只有一個業務處理服務,而是多臺伺服器同時進行某一個相同業務的服務。所以我們需要根據業務形態設計一種架構方式,將來自外部客戶端的業務請求分擔到每一個可用的業務節點上。如下圖所示:


負載層還有一個作用,是根據使用者的請求規則,將不同的請求型別分派到不同的伺服器上。例如:如果某一個HTTP請求是請求一張圖片,那麼負載層會直接到圖片儲存介質上尋找相應的圖片;如果某一個HTTP請求是提交的一張訂單,那麼負載層會根據規則將這張訂單提交傳送到指定的“訂單服務”節點上。


不同的業務需求,使用的負載層方案也是不同的,這就考驗架構師的方案選擇能力。例如Nginx只能處理TCP/IP協議的之上應用層HTTP協議,如果要處理TCP/IP協議,則要按照第三方的TCP-Proxy-Module模。更好的直接在TCP/IP層負載的方案,是使用HAProxy。


常用的負載層架構方式包括: 


– 獨立的Nginx負載或HAProxy方案 
– LVS(DR)+ Nginx方案 
– DNS輪詢 + LVS + Nginx方案 
– 智慧DNS(DNS路由) + LVS + Nginx方案


隨後的文章中將詳細介紹這些負載架構方案以及這些方案的變形。

3、業務服務層和通訊層


3.1、概述

通俗來講就是我們的核心業務層,訂單業務、施工管理業務、診療業務、付款業務、日誌業務等等。如下圖所示:


很明顯在中大型系統中,這些業務不可能是獨立存在的,一般的設計要求都會涉及到子系統間脫耦:即X1系統除了知曉底層支撐系統的存在外(例如使用者許可權系統),X1系統不需要知道和它邏輯對等的X2系統的存在就可以工作。這種情況下要完成一個較複雜業務,子系統間呼叫又是必不可少的:例如A業務在處理成功後,會呼叫B業務進行執行;A業務在處理失敗後,會呼叫C業務進行執行;又或者A業務和D業務在某種情況下是不可分割的整體,只有同時成功才成功,其中有一個失敗整個大的業務過程都失敗。如下圖所示:


這樣一來業務間的通訊層又是一個逃不開的話題。 在隨後的文章中,我們將以Alibaba的Dubbo框架、基於AMQP協議的訊息佇列和Kafka訊息佇列技術的原理和使用方式,來講解業務通訊層技術,特別是業務通訊層的技術選型註意事項。


3.2、不得不提的HTTP請求方式


有的讀者可能會問,為什麼業務系統間通訊層沒有提到HTTP這樣的呼叫方式。畢竟很多公司目前都採用這種方式作為業務系統間的呼叫方式。我們首先透過一個圖來看看HTTP方式的呼叫過程。(註意,此過程不考慮http客戶端快取的過程也不考慮DNS域名解析的過程,從HTTP建立可靠的TCP連線開始):


從上圖中我們可以看出以下幾個問題:


  • 從技術原理層面看,HTTP請求是在需要進行呼叫時建立TCP連線,並且傳送並等待資料回送,在得到請求結果後,可能需要再關閉這個TCP連線。這樣的原理使得很多時間浪費在和業務無關的技術特性上。

  • 另外,傳送Head資訊和接收Head這樣的資料,對業務資料來說是毫無意義的。在訪問量較小的情況下,這樣的過程都還是可以接收的,但是當頻寬資源吃緊的情況下,這樣的資料空間就是彌足珍貴的。

  • 獨立的HTTP請求由於沒有SOA結構中的“治理中心”的概念,所以單純的HTTP請求很難保證負責業務聯動中的背景關係一致性。當然你可以自行編碼來保證,但那樣真的合理嗎?

  • 最後,需要說明的是,現在類似Apache HTTP Components這樣的元件提供了HTTP Pool來減少TCP連線時長,但這僅僅是優化了HTTP作為業務間通訊時的一個問題,其他的問題依然存在。


基於以上的描述,本文並不推薦使用HTTP作為業務間通訊/呼叫的方式,而建議HTTP方式僅限於WEB、iOS、Android等這樣的客戶端請求服務的方式。


4、資料儲存層


資料儲存將是這個系列文章中將要介紹的另一個重點。進行業務計算前的初始資料、計算過程中的臨時資料、計算完成後得到的計算結果都需要進行儲存。我們透過一張思維導圖首先從幾個維度闡述一下資料儲存的基本分類。


4.1、檔案儲存原理


我們透過一個最基本的在Centos6.5系統上建立Ext4檔案系統的過程,講解檔案系統的最基本原理。


  • 首先我們會透過fdisk命令對本地硬碟進行分割槽(即確定可控制的扇區的範圍),如下圖所示:


  • 然後我們會在這個區上面透過mkfs命令建立我們想要的檔案系統(Ext3、Ext4、LVM、XF、BTRFS等),如下圖所示:


  • 最後我們掛載這個檔案系統到指定的路徑,如下圖所示:


  • 透過df命令檢視掛載資訊,如下圖所示: 



  • 萬變不離其宗的建立過程告訴我們一個什麼事實呢?


  • 物理塊,一個物理塊是我們上層檔案系統能夠操作的最小單位(通常為512位元組),一個物理塊在底層對應了多個物理扇區。通常一塊SATA硬碟會有若干機械手臂(決定於物理碟片數量),和若干個物理扇區(物理扇區的大小是磁碟出廠時就確定的,我們無法改變)。

  • 單個扇區的工作是單向的,那麼映射出來的一個物理塊的工作方式也是單向的。原理就是機械手臂在讀取這個扇區的資料時,硬體晶片是不允許機械手臂同時向這個扇區寫入資料的。

  • 透過上層檔案系統(EXT、NTFS、BTRFS、XF)對下層物理塊的封裝,OS是不需要直接操作磁碟物理塊的,操作者透過ls這樣的命令看到的一個一個檔案也不需要關心這些檔案在物理塊的儲存格式。這就是為什麼不同的檔案系統有不同的特性(有的檔案系統支援快照,有的檔案系統支援資料恢復),基本原理就是這些檔案系統對下層物理塊的操作規範不一樣。


4.2、塊儲存和檔案儲存


上一小節我們敘述了最簡單、最原始的物理塊和檔案格式規範的工作方式,但是隨著伺服器端不斷擴大的資料儲存容量的需求和資料安全性的需求,很顯然單機的儲存是沒辦法滿足要求的,目前儲存環境兩種大的需求型別是:


  • 穩定的擴充套件儲存容量,並且不破壞目前已儲存的資料資訊,不影響整個儲存系統的穩定性。

  • 檔案共享,讓多臺伺服器能夠共享儲存資料,並且都可以對檔案系統進行讀寫操作。


要解決這兩個問題,我們首先要將問題擴充套件到上一小節的圖例中,如下圖所示:

很明顯圖中兩個問題的答案是肯定的,也就是我們將要介紹的塊儲存系統要解決的問題。


4.2.1、塊儲存系統


我們先來聊一下塊儲存。之前我們提到的最簡單的情況就是磁碟在本地物理機上,傳輸的物理塊I/O命令,也是透過本地物理機主機板上的南橋進行的。但是為了擴充套件更大的磁碟空間,並且保證資料吞吐量,我們需要將磁碟介質和本地物理機分離,並且讓物理塊的I/O命令在網路上進行傳輸:


  • 雖然磁碟介質和本地物理機發生了分離,但是直接傳輸塊I/O命令的本質是沒有改變的。本地南橋傳輸I/O命令變成了光纖傳輸,只在本物理機內部傳輸I/O命令變成了網路傳輸,並且I/O命令透過某種通訊協議進行了規範(例如FC、SCSI等)。

  • 檔案系統的對映卻是在本地進行,而非遠端的檔案系統對映。上文中我們已經提到,由於塊操作的順序性(在一個扇區進行寫入的時候,是不會進行這個扇區的讀取操作的),且塊操作屬於底層物理操作無法向上層的檔案邏輯層主動反饋變化。所以多個物理主機是無法透過這個技術進行檔案共享的。

  • 塊儲存系統要解決的是大物理儲存空間、高資料吞吐量、強穩定性的共存問題。作為上層使用這個檔案系統的伺服器來說,它非常清楚,除了它以外沒有其他的伺服器能夠對專屬於它的這些物理塊進行讀寫操作了。也就是說它認為這個龐大容量的檔案儲存空間只是它本地物理機上的儲存空間。

  • 當然隨著技術的發展,現在已經有一些技術可以只用TCP/IP協議對標準的SCSI命令進行傳輸,以便減小這個塊儲存系統的建設成本(例如iSCSI技術)。但是這種折中方式也是以減弱整個系統的資料吞吐量為代價的。不同的業務需求可以根據實際情況進行技術選型。


4.2.2、檔案儲存系統


那麼如果是將檔案系統從本地物理機透過網路移植到遠端呢?當然可以,典型的檔案儲存系統包括了FTP、NFS、DAS: 


  • 檔案儲存系統的關鍵在於,檔案系統並不在本機。而是透過網路訪問存在於遠端的檔案系統,再由遠端的檔案系統操作塊I/O命令完成資料操作。

  • 一般來說諸如本地檔案系統NTFS/EXT/LVM/XF等是不允許直接網路訪問的,所以一般檔案儲存系統會進行一層網路協議封裝,這就是NFS協議/FTP協議/NAS協議(註意我們說的是協議),再由協議操作檔案儲存系統的伺服器檔案系統。

  • 檔案儲存系統要解決的問題首要的檔案共享,網路檔案協議可以保證多臺客戶端共享伺服器上的檔案結構。從整個架構圖上可以看到檔案儲存系統的資料讀寫速度、資料吞吐量是沒辦法和塊儲存系統相比的(因為這不是檔案儲存系統要解決的首要問題)。


從上面的簡介中我們可以清楚的知曉,當面對大量的資料讀寫壓力的時候,檔案儲存系統肯定不是我們的首要選擇,而當我們需要選擇塊儲存系統時又面臨成本和運維的雙重壓力(SAN系統的搭建是比較複雜的,並且裝置費用昂貴)。並且在實際生產環境中我們經常遇到資料讀取壓力大,且需要共享檔案資訊的場景。那麼這個問題怎麼解決呢?


4.3、物件儲存系統


兼具塊儲存系統的高吞吐量、高穩定性和檔案儲存的網路共享性、廉價性的物件儲存就是為了滿足這樣的需求出現的。典型的物件儲存系統包括:MFS、Swift、Ceph、Ozone等。下麵我們簡單介紹一下物件儲存系統的特點,在後面的文章中,我們將選擇一款物件儲存系統進行詳細說明。


物件儲存系統一定是分散式檔案系統。但分散式檔案系統不一定是物件儲存系統


  • 我們知道檔案資訊是由若干屬性進行描述的,包括檔案名、儲存位置、檔案大小、當前狀態、副本數量等資訊。我們將這些屬性抽離出來,專門使用伺服器進行儲存(元資料伺服器)。這樣一來檔案操作的客戶端要訪問某一個檔案,首先會詢問元資料節點這個檔案的基本資訊。

  • 由於是分散式系統,那麼資料一致性、資源爭奪、節點異常問題都需要進行統一的協調。所以物件儲存系統中一般會有監控/協調節點。不同的物件儲存系統,支援的元資料節點和監控/協調節點的數量是不一致的。但總的趨勢都是“去中心化”。

  • OSD節點(基於物件的儲存裝置)用於儲存檔案內容資訊。這裡要註意,雖然OSD節點的底層和塊儲存底層一樣都是依靠塊I/O進行操作的,但是上層構造兩者完全不同:OSD節點並非向塊儲存裝置那樣,透過塊操作命令跳過本地檔案系統直接進行物理塊操作。

  • 隨後的文章中我們將選擇一款流行的物件儲存系統,詳細剖析物件儲存系統,並且對分散式儲存系統中三個核心概念和取捨進行說明(CAP):一致性、擴充套件性和容錯性。


4.4、資料庫儲存


這篇文章已經寫了很多儲存層的概要描述了,所以我們熟悉或者不熟悉的資料庫儲存技術的概述就不在這裡介紹了。


後續的文章我將使用Mysql講解幾個常用的架構方案和效能最佳化點,當然也會講到Mysql中,諸如Innodb這樣的核心資料引擎的工作方式。這些架構方案主要解決的是Mysql的單機I/O瓶頸、機房內資料容災、資料庫穩定性、跨機房資料容災等核心問題。


後續的文章我還會選取目前流行的資料快取系統,講解其工作原理、核心演演算法和架構方案。以便讀者們根據自己的業務情況設計符合業務的儲存叢集。當然還有非關係型資料庫Cassandra、HBase、MongoDB的深入介紹。

5、評價架構的特性

我們如何來評價一個服務系統的頂層設計是否優秀呢?拋開八股文式的擴充套件性、穩定性、健壯性、安全性這樣的套話不說。我從實際工作中為大家總結了一下幾個評價要點。


5.1、建設成本


任何系統架構在進行生產環境實施的時候,都是需要付出建設成本的。顯然各個公司/組織對成本的承受度是不一樣的(這些成本包括:設計成本、資產採購成本、運維成本、第三方服務成本),所以如何利用有限的成本建設出符合業務需求、適應訪問規模的系統,就是一個複雜的問題。另外,這種要求下架構師是不能進行過度設計的。


5.2、擴充套件/規划水平


根據業務的發展,整個系統是需要進行升級的(這包括已有模組的功能升級、合併已有的模組、加入新的業務模組或者在模組功能不變的情況下提高資料吞吐量)。那麼如何儘量不影響原業務的工作,以最快的速度、最小的工作量來進行系統的橫向、縱向擴充套件,也就是一個複雜的問題了。好的系統架構是可以在使用者無任何感覺的情況下進行升級的,或者只需要在某些關鍵子系統升級時才需要短暫的停止服務。


5.3、抗攻擊水平


對系統的攻擊肯定是瞄準整個系統最薄弱的環節進行的,攻擊可能來自於外部(例如Dos/DDos攻擊)也可能來自於內部(口令入侵)。好架構的系統不是“絕對不能攻破”的系統,而是“預防很好”的系統。所謂預防,就是預防可能的攻擊,分階段對可能遇到的各種攻擊進行模擬;所謂隱藏,就是利用各種手段對整個系統的關鍵資訊進行涉密管理,ROOT許可權、物理位置、防火牆引數、使用者身份。


5.4、容災恢復等級


好的架構應該考慮不同等級的容災。叢集容災,在叢集中某一個服務節點崩潰的情況下,叢集中另外一臺主機能夠接替馬上接替他的工作,並且故障節點能夠脫離;分散式容災:分散式系統一般會假設整個系統中隨時都在發生單點故障/多點故障,當產生單點故障/多點故障時,整個分散式系統都還可以正常對外提供服務,並且分散式系統中的單點故障/多點故障區可以透過自動/人工的方式進行恢復,分散式系統會重新接納它們;異地容災(機房等級容災):在機房產生物理災難的情況下(物理網路斷裂、戰爭摧毀、地震等),在某個相隔較遠的異地,備份系統能夠發現這樣的災難發生,並主動接過系統執行權,通知系統運維人員(根據系統不同的執行要求,可能還有多個備份系統)。異地容災最大的挑戰性是如何保證異地資料的完整性。


5.5、業務適應性水平


系統架構歸根結底還是為業務服務的,系統架構的設計選型一定是以服務當前的業務為前提。在上文中提到的業務通訊層中,選擇SOA元件還是訊息佇列元件,又或者選擇什麼樣的訊息佇列,就是一個很好的業務驅動事件。例如,A業務是一種WEB前端服務,需要及時反饋給客戶操作結果,B業務的服務壓力又非常大。A業務在呼叫B業務時,B業務無法在毫秒級的時間內傳回給A業務呼叫結果。這種業務場景下可以使用AMQP型別的訊息佇列服務。另外說明兩點,目前行業內有很多為解決相同業務場景存在的不同方案,架構師在進行方案選型的過程中,一定要對各種解決方案的特點足夠掌握,這樣才能做出正確的選擇;另外行業內的解決方案已經足夠多,架構師在業務沒有特殊要求的情況下一定不要做“ 重覆發明輪子”的事情。


5.6、維護難易程度


一套服務系統從架設之初就需要運維團隊不斷的進行投入。顯然根據系統的複雜程度和物理機器的數量,運維團隊的知識複雜性也是不一樣的。在架構師進行頂層架構設計時,必須還要考慮系統的運維難度和運維成本。


6、其他說明


  • 負載層、業務層、業務通訊層、資料儲存層的詳細架構方案在後續文章中我們會用若干文章進行深入講解,包括核心演演算法、架設原理、架設案例。隨後的文章中我們將首先介紹系統負載層。

  • 在很多系統中我們還涉及儲存的資料進行分析,形成資料分析結果。這涉及到資料分析層的架構知識。Hadoop生態系統是目前行業公認的高效率、高穩定性、高擴充套件性的資料分析生態系統。這個系列的博文暫時不會介紹資料分析層的架構設計和開發知識,後續將會獨立成文。

  • 各位看官我們馬上進入負載層技術的詳細講解!


編號739,輸入編號直達本文

●輸入m獲取文章目錄

推薦↓↓↓

Web開發

更多推薦18個技術類微信公眾號

涵蓋:程式人生、演演算法與資料結構、駭客技術與網路安全、大資料技術、前端開發、Java、Python、Web開發、安卓開發、iOS開發、C/C++、.NET、Linux、資料庫、運維等。

贊(0)

分享創造快樂