上面的圖示清楚表示了網站體系架構。如果你不是經驗豐富的網頁開發人員,可能會覺得它很複雜。在我們深入探究每個部分之前,下面的描述應該會讓我們更容易上手。
一位用戶在 Google 上搜尋「森林中的濃霧和陽光」。第一個結果應該會來自於 Storyblocks — 我們最大的照片和向量圖網站。當用戶點擊結果,瀏覽器將畫面轉向到圖片的詳細資訊頁面。事實上,過程就是瀏覽器在後台將請求發送到 DNS 服務器,以查詢如何聯繫 Storyblocks 網站,然後發送請求。
當請求到達負載平衡器,它會在我們當時運行網站的大約十台網站服務器中,隨機選擇一個來處理請求。網站服務器從我們的暫存服務中查尋有關該圖像的一些訊息,並從資料庫中獲取有關該圖像的其他資料。由於我們注意到圖像的顏色配置文件尚未被計算,我們將「顏色配置文件」工作發送到作業佇列,然後我們的作業服務器會對其進行異步處理,並根據結果適當地更新資料庫。
接下來,我們嘗試將照片的標題作為輸入,向全文檢索服務發送請求,來查尋相似的照片。用戶剛好以會員的身份登錄 Storyblocks 網站,因此我們從帳戶服務中查尋其帳戶訊息。最後,我們向資料串流觸發一個頁面查看事件,以記錄到我們的雲端系統,並最終加載到我們的資料庫中,它被用來幫助分析人員們回答有關業務的問題。
現在,服務器將視圖渲染為 HTML,首先通過負載平衡器,然後將其發送回用戶的瀏覽器。該頁面包含我們加載到與 CDN 連接雲端系統中的 JavaScript 和 CSS 內容,因此用戶的瀏覽器聯繫 CDN 以檢索內容。最後,瀏覽器將頁面可視化,呈現給用戶觀看。
接下來,我將帶你逐步了解每個組件,並為每個部分提供完整的介紹,同時帶給你一個良好的思維模式,來思考未來的網站體系架構。
1. 域名系統 DNS
DNS 代表「域名系統」,它是使全球資訊網(world wide web)成為可能的主要技術。最基本來說,DNS 提供從域名(例如 google.com)到 IP 位址(例如 85. 129. 83. 120)的鍵/值查尋,這是你的電腦將請求路由到適當位址的必要服務器。與電話號碼類似,域名和 IP 位址之間的區別就是「打電話給 John Doe」和「打電話給 201-867-5309」之間的區別。就像你過去需要一本電話簿來查尋 John 的電話號碼一樣,你需要 DNS 來查尋域名的 IP 地址。因此,你可以將 DNS 視為互聯網的電話簿。
我們將跳過更多詳細介紹,因為這對於我們的整體介紹並不重要。
2. 負載平衡器 Load Balancer
在深入研究負載平衡之前,我們需要退後一步來討論水平與垂直的應用擴展。它們是什麼,以及有什麼區別?在
此 StackOverflow 貼文中可以讓你非常簡單地了解,
水平擴展意味著向資源池中添加更多虛擬機器來進行擴展,而垂直擴展意味著向現有虛擬機器中添加更多的功能(例如 CPU、RAM)來進行擴展。
在網站開發中,你(幾乎)總是想用水平擴展,因為為了簡單起見,東西會中斷、服務器隨時會崩潰、網路會出問題、整個資料中心有時會斷線。擁有多台服務器可以使你為中斷做計劃,以讓應用程式繼續運行。換句話說,你的應用程式是「容錯的」。其次,水平擴展允許你藉由使它們各自在不同的服務器上運行,來最小化結合應用程式後端的不同部分(網站服務器、資料庫、某服務等)。最後,你可能會達到無法再垂直擴展的程度。世界上沒有夠大的虛擬機器來執行你所有應用程式的計算。儘管這適用於規模較小的公司,但可以將 Google 的搜尋平台視為一個典型的例子。例如,Storyblocks 網站在任何時間點運行 150 到 400 個 AWS EC2 事例。通過垂直擴展來提供全部計算能力將會是一個挑戰。
好,回到負載平衡器。它們是使水平擴展成為可能的魔術棒。它們將請求傳入到通常彼此克隆或鏡像的眾多應用程式服務器之一,並將回應從應用程式服務器發送回用戶端。它們當中的任何一個都該會以相同的方式處理請求,因此只需在服務器之間分配請求,這樣就不會使它們過載。
就這樣。從概念上來說,負載平衡器相當地簡單理解。事實上肯定有許多復雜之處,但在此處無需深入了解。
3. 網站應用服務器 Web Application Servers
綜觀來看,網站應用程式服務器的描述相對簡單。它們處理用戶請求的核心業務邏輯,並將 HTML 發送回用戶的瀏覽器。為了完成工作,他們通常與各種後端基礎架構進行通信,例如資料庫、暫存層、作業佇列、搜尋服務,其他微服務,資料/日誌記錄佇列等等。如上所述,為了處理用戶請求,通常將至少兩個(通常是更多)插入負載平衡器。
你應該知道,應用服務器的實行需要選擇一種特定的語言(Node.js、Ruby、PHP、Scala、Java、C#、.NET等)和該語言的網站 MVC 框架(Express for Node.js、Ruby on Rails、Play for Scala、Laravel for PHP 等等)。但是,深入探討這些語言和框架的細節不在本文的討論範圍之內。
4. 資料庫服務器 Database Servers
每個現代的網站應用程式都利用一個或多個資料庫來存儲訊息。資料庫提供了定義資料結構、插入、查尋、更新或刪除現有資料,以及對資料進行計算等方法。在大多數情況下,網站應用程式服務器與作業服務器直接進行通信。此外,每個後端服務可能都有自己的資料庫,並與應用程式的其餘部分隔離。
儘管我避免深入探討每個體系結構中的特定技術,但重要的來了,資料庫的下個細節:SQL 和 NoSQL。
SQL 代表「結構化查詢語言」,於 1970 年代發明,提供了一種標準的查詢關係資料集的方法,讓廣大的使用者進行訪問。SQL 資料庫將資料存儲在透過用 ID(通常為整數)連接在一起的列表中。讓我們來看看一個為用戶儲存歷史地址訊息的簡單範例。你可能有兩個列表,用戶列表和用戶地址列表,透過用戶的 ID 連接在一起。參見下圖的簡化版本。這些表被連接,因為 user_addresses 中的 user_id 列是 users 表中 id 列的「外鍵」。
如果你對 SQL 不太了解,我強烈建議你逐步學習,就像你可以在
Khan Academy 上找到的課程那樣。它在網站開發中無所不在,因此你至少要了解基礎知識,以便正確地構建應用程式。
NoSQL 代表「非 SQL」,它是一組較新的資料庫技術,可以處理大型網站應用程式可能產生的大量資料(大多數 SQL 變體不能很好的水平擴展,並且只能垂直擴展到某個點)。如果你對 NoSQL 一無所知,建議從以下介紹入手:
5. 暫存服務 Caching Service
暫存服務提供了一個簡單的鍵/值資料存儲,使你可以在接近 0(1)的時間內保存和查尋資訊。應用程式通常利用暫存服務來保存珍貴的計算結果,以便從暫存中檢索結果,而不用在下次需要時重新計算。應用程式可能會從資料庫查詢暫存結果、調用外部服務和給定 URL 的 HTML 等結果。以下是應用程式中的一些真實範例:
- Google 會為常見搜尋查詢(例如「狗」或「泰勒·斯威夫特」)暫存搜尋結果,而不是每次都重新計算它們。
- Facebook 會暫存你登錄時看到的許多資料,例如貼文資料、朋友等。在此處閱讀有關Facebook 暫存技術的詳細文章。
- Storyblocks 暫存來自服務器端的 React 渲染、搜尋結果、預輸入結果等的 HTML 輸出。
兩種最廣泛被使用的暫存服務器技術是 Redis 和 Memcache。我將在另一篇文章中詳細介紹。
6. 作業佇列和服務器 Job Queue & Servers
大多數網站應用程式需要在後台異步執行一些與用戶請求沒有直接相關的工作。例如,Google 需要對整個網際網路進行爬蟲並編制索引,以便返回搜尋結果。在你搜尋時,它不會每次都這樣做。而是藉由異步爬蟲,一路更新搜尋索引。
儘管有不同的體系結構可以完成異步工作,但最普遍的是我稱之為「作業佇列」的體系結構。它由兩個部分組成:一個需要運行的「作業」佇列,和一個或多個運行該作業佇列的作業服務器(通常被稱為「工人」)。
作業佇列需要進行異步來儲存作業列表。儘管大多數應用程式最終都需要某種優先級的排程系統,最簡單的是先進先出(first-in-first-out、FIFO)佇列。每當應用程式需要按照某種常規,或是根據用戶操作確定要運行作業時,它只會將適當地將作業添加到佇列中。
例如,Storyblocks 網站利用在幕後的工作佇列來讓我們許多交易得以實現。我們運行作業以對影片和照片進行編碼、處理 CSV 檔案以進行後設資料標記、匯總用戶統計資訊和發送重置密碼的電子郵件等。我們從簡單的 FIFO 佇列開始,現在我們用到優先級佇列,以確保像是發送重置密碼電子郵件之類的緊急操作能盡快完成。
作業服務器處理作業。他們會不斷詢問作業佇列是否有工作要做,如果有,他們將作業從佇列丟出並執行。基本語言和框架的選擇與網站服務器一樣多,因此在本文中我將不做詳細介紹。
7. 全文檢索服務 Full-text Search Service
許多網絡應用程式都支持某種搜尋功能,當用戶提供文字輸入(通常稱為「查詢」),應用程式返回最「相關」的結果。支持此功能的技術通常被稱為「
全文搜尋」,它利用
反向索引快速查尋包含關鍵字的文檔。
該範例顯示如何將三個文檔標題轉換為反向索引,以從特定關鍵字到標題中快速查尋帶有該關鍵字的文檔。注意,諸如 in、the、with 等的常用詞(或稱為停用詞)通常不包括在反向索引中。
8. 服務 Services
一旦應用程式達到一定規模,就有可能將某些「服務」劃分為單獨的應用程式來運行。它們不會暴露於外部,但是會與其他服務進行交互。例如,Storyblocks 網站具有多項營運和計劃服務:
- 帳戶服務:在我們所有網站上存儲用戶資料,這使我們能夠輕鬆地提供交叉銷售機會,並創建更統一的用戶體驗。
- 內容服務:儲存我們所有影片、音頻和圖像內容的後設資料。它還提供了下載內容和查看下載歷史的界面。
- 付款服務:提供了為客戶信用卡計費的介面。
- HTML 轉 PDF 服務:提供了一個簡單的界面,該界面接受 HTML 並返回對應的 PDF 檔案。
9. 資料 Data
如今,公司的存續取決於他們如何利用資料。幾乎每個應用程式一旦達到一定規模,就會利用資料管道來收集、儲存和分析資料。典型的管道具有三個主要階段:
- 應用程式將資料(通常是和用戶交互有關的事件)發送到資料串流,該串流提供了介面以提取和處理資料。通常原始資料會被轉換或擴充並傳遞給另一個防火牆。AWS Kinesis 和 Kafka 是最常見的技術。
- 原始資料以及最終的轉換/增強資料會被保存在雲端中。AWS Kinesis 提供了一個稱為「串流(firehose)」的設置,將原始資料保存到其雲端(雅馬遜的 S3)的過程非常容易配置。
- 轉換/增強的資料通常被加載到資料庫中進行分析。儘管大型公司通常會使用 Oracle 或其他專有資料庫技術,但我們使用 AWS Redshift,它也是新興領域中龐大且不斷成長的部分。如果資料集足夠大,則可能需要類似 Hadoop 的 NoSQL MapReduce 技術來進行分析。
架構圖中未顯示的另一步驟:從應用程式和服務的資料庫將資料加載到資料庫中。以 Storyblocks 網站為例,我們每晚將 VideoBlocks、AudioBlocks、Storyblocks、帳戶服務和貢獻者入口資料庫加載到 Redshift 中。藉由將核心業務資料與我們的用戶交互事件資料一起定位,可以為我們的分析師提供一個整體資料集。
10. 雲端 Cloud storage
根據
AWS 的說法,「雲端是一種透過網路儲存、訪問和共享資料的簡單且可擴展的方式」。你可以用它來儲存或訪問在本地檔案系統上儲存的任何內容,其優點是可以通過基於 HTTP 的 RESTful API 交互。目前為止,雅馬遜的 S3 產品是最受歡迎的雲端,我們在 Storyblocks 網站廣泛依賴它來儲存影片、照片和音訊檔案、CSS 和 JavaScript,以及我們的用戶事件資料等等。
11. 內容傳遞網路 CDN
CDN(Content Delivery Network) 代表「內容傳遞網路」,該技術提供了一種在網站上為靜態 HTML、CSS、JavaScript 和圖像之類的檔案提供服務的方法,速度比從單個原始服務器提供這些資源要快得多。它的工作原理是將內容分佈於世界各地的許多「邊緣」服務器上,以讓用戶最終從「邊緣」服務器而不是原始服務器下載檔案。例如在下圖中,在西班牙的用戶從具有紐約原始服務器的網站發出請求,但是該頁面的靜態檔案是從英格蘭的 CDN「邊緣」服務器加載的,從而避免了許多跨大西洋的 HTTP 緩慢請求。
查看這篇文章以獲得更全面的介紹。通常網站應用程式應始終使用 CDN 來提供 CSS、JavaScript、圖像、影片和任何其他檔案。一些應用程式也可能能夠利用 CDN 來提供靜態 HTML 頁面。
其他想法
以上就是網站架構原理的總結。希望對你有幫助。我會在接下來的一、兩年中發表一系列的文章,深入探討其中一些內容。
本文翻譯自:
感謝您的閱讀,我試著將生活與自己所學到的知識,以平易近人的方式傳達給正在努力進步的同好,甚至是領域之外卻有興趣的人。如果喜歡我的文章,歡迎贊助我,你的鼓勵也是我進步的動力。