[譯] Web 應用架構基礎課

horizon13th發表於2018-08-07

初級 web 應用開發者必學的基礎網路架構概念

[譯] Web 應用架構基礎課

web 應用主流架構概覽

上圖便是我司(Storyblocks)網路架構的很好展現。如果你還沒成為經驗老道的 web 工程師,可能覺得上圖巨複雜。在詳解各個模組前,我們先簡單過一下流程。

使用者在 Google 搜尋關鍵字 “Strong Beautiful Fog And Sunbeams In The Forest”,首條結果便是來自我司的拳頭產品:Storyblocks —— 圖片向量圖素材站,使用者點選搜尋結果進入圖片詳情頁。在使用者操作的背後,客戶端瀏覽器向 DNS 伺服器查詢圖片所在伺服器,併傳送訪問請求。

使用者請求通過負載均衡(隨機選擇多個伺服器中的一個)訪問站點處理請求。伺服器從快取服務中查詢圖片資訊,並從資料庫中調取其它資訊。我們注意到此時,圖片尚未進行色彩渲染計算,便傳送“色彩渲染”任務到任務佇列。此時該服務所在伺服器非同步處理任務,適時將結果更新到資料庫。

接下來,我們嘗試匹配相似圖片,以圖片標題作為輸入,進行全文搜尋服務。使用者登入系統,系統通過賬戶服務查詢賬戶資訊。最後,系統將該頁面檢視事件作為日誌流處理並在雲端儲存系統中記錄,再錄入資料倉儲,供資料分析師做之後的商業分析。

伺服器將渲染的 HTML 頁面先經過負載均衡,再返回到使用者瀏覽器。頁面包含 Javascript 指令碼和 CSS 資原始檔,存於與我們的 CDN 相連的雲端儲存系統中,使用者瀏覽器直接通過 CDN 獲取內容。最後,瀏覽器顯式地渲染頁面,供使用者瀏覽。

下面,我們就每一個元件詳細討論,做最最基礎的介紹,幫你建構認知模型,思考整個前面提到的整個網路服務架構。之後我還會發布其它文章,基於在我司學習到的內容,為大家更有針對性地從實踐角度做推薦。

1. DNS

DNS(Domain Name Server)是域名伺服器的簡稱,它是網際網路依存的基礎設施。簡單來說,DNS 提供域名與 IP 地址的鍵值對查詢,例如(google.com 域名對應 85.129.83.120 IP 地址),這非常有必要,它讓你的電腦通過請求尋路到特定伺服器。就好比打電話,域名與 IP 地址的關係類似於聯絡人和電話號碼的關係。以前你需要電話號碼簿記錄他人的電話號碼,現在你需要 DNS 伺服器尋找域名對應的 IP 地址。所以你可以把 DNS 想象成網際網路世界的電話簿。

這裡我們還有很多細節可以深入,暫時先跳過,因為這不是我們基礎課的重點。

2. 負載均衡

在詳解負載均衡之前,我們先退一步討論一下應用的縱向擴充套件和橫向擴充套件。兩者有什麼區別?簡單來說,參考 StackOverflow 的這篇帖子,橫向規模擴充套件意味著通過在資源池中加機器,縱向擴充套件意味著在已有機器上增強算力(如 CPU,RAM)。

在 web 開發絕大多數情況下,會選擇橫向擴充套件。理由很簡單,伺服器會當機,網路會斷線,資料中心會掉電。多臺伺服器可以保證你的應用在能夠一邊停機維護,一邊持續工作。換句話說,應用能夠“容錯”。另外,橫向擴充套件能最小限度地耦合不同後臺服務(web 伺服器,資料庫,等等),使不同服務在不同機器上執行。還有一點,縱向擴充套件是有上限的,到達一定限度就無法再擴充套件。世界上也不存在一臺超算計算機承載應用的所有計算,典型例子想象一下 Google 的搜尋平臺,哪怕其它公司達不到這麼大的規模。其它公司,比如我司,Storyblocks,任何時候都把服務跑在 150-400 個 AWS EC2 例項上。通過縱向擴充套件提供算力是相當有挑戰的。

回到負載均衡,可以說它是橫向擴充套件的黑魔法。它將傳入請求轉路到多個伺服器中的其中一個,再將響應回傳給客戶端。多個伺服器彼此作為映象,任意機器都會以同樣的方式處理請求。向服務叢集分發訊息,便不會出現單個伺服器過載的情況。

理論上負載均衡就這些要點,很簡單直接。當然了,簡單的理論背後有更多細節,這篇入門文章裡我們不再贅述。

3. Web 應用伺服器

從上層角度來看,web 應用伺服器相對好理解,它們用來處理核心業務邏輯,處理使用者請求,給客戶端瀏覽器返回 HTML。處理這些任務便是與後臺基礎設施間通訊,比如資料庫、快取服務、任務佇列、搜尋服務、其它微服務和訊息/日誌佇列等等。一般情況下至少兩個應用伺服器,或者更多,這些應用服務接入負載均衡,處理使用者請求。

應用伺服器的實現通常需要某種特定語言(Node.js, Ruby, PHP, Scala, Java, C# .NET 等)和對應的 MVC 框架上(Node.js 的 Express、Ruby on Rails、Scala 的 Play、PHP 的 Larave 和 Java 的 Spring 等等)。語言和框架的細節我們這裡不做贅述,有興趣的讀者可以自行深入研究。

4. 資料庫伺服器

任意現代 Web 應用都使用一個甚至多個資料庫來儲存資訊。資料庫用來定義資料結構,對資料進行增刪改查,高階運算操作等等。多數情況下,web 應用伺服器與一個資料庫進行直接通訊,任務伺服器同理。另外,每個後臺服務都有一個自己的資料庫,並與其它的應用隔離。

儘管在本文中,我們儘量避免深入討論架構中的某個特定技術,這裡我還是想特殊地提一下資料庫中的 SQL 和 NoSQL。

SQL(Structured Query Language)全稱結構化查詢語言,1970 年代釋出,提供了查詢關係型資料庫的一種標準形式,並廣為大眾接受。SQL 資料庫將資料以表的形式儲存,通過 ID (通常為 int 整型)這種方式使表之間相互關聯。舉個簡單的例子,我們想要儲存使用者的歷史地址資訊。需要準備兩張表,使用者表 users 和使用者地址表 user_addresses,並通過 user_id 進行關聯,如下圖。表間相關聯是通過在 user_addresses 表中使用 user_id 作為外來鍵實現的。

[譯] Web 應用架構基礎課

如果你不瞭解 SQL,這裡推薦可汗學院的課程學習。在 web 開發中 SQL 非常普遍,瞭解其基礎作為應用架構還是很有必要的。

NoSQL,如其字面意思,“非-SQL”,是一種新型資料庫,用來應對大規模 web 應用中的海量資料(大部分 SQL 不能很好支援橫向擴充套件,只能從某些方面支援縱向擴充套件)。如果你完全不瞭解 NoSQL,推薦下列文章:

我還想順便提一點,業界通常使用 SQL 作為 NoSQL 資料庫的表層呼叫,不懂 SQL 的話還是很有必要去學習的,如今的業務場景很難避開它。

5. 快取服務

快取服務提供一種簡單的鍵值對資料儲存,使存取資訊時間複雜度接近 O(1) 。應用內通常使用快取服務儲存運算成本高昂的運算結果,再次請求時從快取中檢索結果,而非在每次請求時都重新計算。快取內容可以是資料庫查詢,外部服務呼叫結果,連結返回的 HTML,等等。下面我們從真實場景中舉例:

  • 搜尋引擎服務(比如百度)會快取一些常見的查詢結果,比如“狗”,“周杰倫”,而不是在每次查詢時都實時計算。
  • 社交網站服務(比如 Facebook)會快取每次登陸時使用者看到的資料,比如最近博文,好友,等等。這裡有一篇 Facebook 如何做快取的文章。
  • 我司(Storyblocks)會快取伺服器端 React 渲染的 HTML 頁面,搜尋結果,預輸入結果,等等。

最常用到的伺服器快取技術是 Redis 和 Memcache。我之後會在其它文章中深入討論。

6. 任務佇列及伺服器

大部分 web 應用背後都有非同步任務在處理,這些任務不必直接響應使用者請求。比如說,谷歌需要爬取整個網際網路並建立索引以返回搜尋結果,但這實際上並不是在你每次搜尋時都實時進行,而是通過非同步方式爬取網路結果並更新索引。

非同步任務有很多不同的方式來完成,最常用的是任務佇列。它包含兩部分:正在執行的任務佇列,和一或多個處理任務的伺服器(通常稱為 workers)。

任務佇列儲存了一系列需要非同步執行的任務。最簡單的任務排程是 FIFO(先進先出)的方式,不過大部分應用使用按優先順序排序的排程方式處理任務。每當一個任務需要被執行,要麼使用統一的排程演算法,要麼是按使用者行為按需排程,該任務便被加入佇列中等待被執行。

舉個例子,我司利用任務佇列,賦能後臺任務以支援營銷活動。我們用後臺任務編碼多媒體檔案如視訊圖片,處理資料如在 CSV 做後設資料標記,聚合使用者行為分析,執行郵件服務比如給使用者傳送重置密碼的郵件,等等。我們最初使用 FIFO 排程任務,後來優化為優先佇列,以保證時間敏感的操作完成的實時性,比如立馬傳送重置密碼郵件。

任務伺服器執行任務時,先檢視任務佇列中是否有任務需要執行,若有任務便彈出該任務並執行。有很多語言和框架可以在伺服器上使用作為任務佇列,這裡不多講。

7. 全文檢索服務

在一些應用中,為使用者提供搜尋功能,使用者輸入文字時(查詢語句)應用返回相近結果。這種技術通常指的是“全文檢索”,運用倒排索引快速查詢包含查詢關鍵字的文件。

[譯] Web 應用架構基礎課

上圖中例子顯示了三個文件標題被轉換成倒排索引,通過某些標題關鍵字能夠快速檢索文件。通常停用詞(英文中的:in、the、with 等,中文中:我、這、和、啊等)不會被加入到索引中。

儘管我們可以直接通過資料庫做全文檢索,比如 MySQL 支援全文檢索,但通常我們會跑一個單獨的“搜尋服務”計算並儲存倒排索引,並提供查詢介面。目前主流的全文檢索服務是 Elasticsearch,還有 SphinxApache Solr 等選擇。

8. 服務

當應用到達一定的規模,通常傾向於拆分其為單個應用,作為“微服務”。外界對這些微服務是不可感知的,但應用內服務間相互通訊。比如我司有各種運維服務和計劃執行服務:

  • 使用者服務 儲存所有平臺網站使用者資料,便捷地提供交叉銷售商機,以及統一的使用者體驗。
  • 內容服務 儲存多媒體檔案的後設資料,並提供檔案下載介面和下載歷史資訊等。
  • 支付服務 提供客戶付款資訊介面。
  • PDF 匯出服務 提供統一介面,將 HTML 轉換成相對應的 PDF 檔案並下載。

9. 資料

如今各大公司成敗在於 “如何很好地管理資料”,在應用到達一定規模時規範資料流程。一般來說有:加工資料、儲存資料和分析資料,這三個步驟:

  1. 資料加工 應用響應使用者互動事件,將資料傳送到資料流處理平臺(提供流資料處理介面)進行處理。通常原始資料被轉換或加工並傳入另一個資料流處理平臺。AWS Kinesis 和 Kafka 是此類資料流處理最常用的工具。
  2. 資料儲存 原始資料和轉換加工後的資料在雲端儲存。例如 AWS Kinesis 提供叫做 “firehose” 的配置,將原始資料儲存在其雲平臺 Amazon S3 上,使用起來極其方便。
  3. 資料分析 轉換加工後的資料會載入入資料倉儲來做後續分析。我司使用 AWS Redshift 作為資料倉儲,很多創業公司也都在用,大型公司一般選擇 Oracle 或者其它的資料倉儲服務。當資料量十分龐大時,可能需要用類 Hadoop 的 NoSQL MapReduce 技術來做後續分析。

還有一個步驟沒有在架構圖中繪出:從應用和服務運維資料庫中把資料匯入資料倉儲。例如在我司,我們每晚都會把各個服務的資料存到 AWS Redshift,把核心業務的資料和使用者互動行為的資料放在一起,提供給我們的資料分析師一個整體化的資料集。

10. 雲端儲存

“雲端儲存既簡單,擴充套件性又好,方便使用者在全網獲取、儲存、分享資料” —— AWS 雲端儲存服務。任意在本地檔案系統儲存的檔案,你都可以通過雲端儲存存取,並用 HTTP 協議通過 RESTful API 訪問並互動。Amazon S3 提供了目前最流行的雲端儲存,我司在其上廣泛儲存各種東西,從多媒體素材、視訊、圖片、音訊,到 CSS、Javascript 乃至使用者行為資料等等。

11. CDN

CDN 指的是內容分發網路,該技術提供一種素材服務,比如儲存靜態 HTML,CSS,Javascript 和圖片。從全網獲取這些靜態素材比從單個源伺服器獲取要快的多。它的工作原理是將內容分佈在世界各地的邊緣伺服器上,而不是僅僅放在一個源節點上。比如說,下圖中一個西班牙的使用者訪問某個源節點位於紐約的網站,但是頁面的靜態素材通過英國的 CDN 邊緣伺服器載入,這樣就避免了冗餘的跨大西洋的 HTTP 請求,提快了訪問速度。

[譯] Web 應用架構基礎課

圖片源

這篇文章 更詳細解釋了為什麼使用 CDN。總的來說,網路應用可以使用 CDN 來儲存諸如 CSS、Javascript 和圖片視訊等素材,甚至靜態 HTML 網頁。

一些想法

以上便是網路應用架構基礎課的全部內容,希望這篇文章對你有幫助。接下來我還會發布進階課的文章,詳細研究上述的某些元件。

如果發現譯文存在錯誤或其他需要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可獲得相應獎勵積分。文章開頭的 本文永久連結 即為本文在 GitHub 上的 MarkDown 連結。


掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章