web 應用主流架構概覽php
上圖即是我司(Storyblocks)網絡架構的很好展示。若是你還沒成爲經驗老道的 web 工程師,可能以爲上圖巨複雜。在詳解各個模塊前,咱們先簡單過一下流程。html
用戶在 Google 搜索關鍵字 「Strong Beautiful Fog And Sunbeams In The Forest」, 首條結果即是來自我司的拳頭產品:Storyblocks —— 圖片矢量圖素材站,用戶點擊搜索結果進入圖片詳情頁。在用戶操做的背後,客戶端瀏覽器向 DNS 服務器查詢圖片所在服務器,併發送訪問請求。
用戶請求經過負載均衡(隨機選擇多個服務器中的一個)訪問站點處理請求。服務器從緩存服務中查找圖片信息,並從數據庫中調取其它信息。咱們注意到此時,圖片還沒有進行色彩渲染計算,便發送「色彩渲染」任務到任務隊列。此時該服務所在服務器異步處理任務,適時將結果更新到數據庫。
接下來,咱們嘗試匹配類似圖片,以圖片標題做爲輸入,進行全文搜索服務。用戶登入系統,系統經過帳戶服務查找帳戶信息。最後,系統將該頁面查看事件做爲日誌流處理並在雲存儲系統中記錄,再錄入數據倉庫,供數據分析師作以後的商業分析。
服務器將渲染的 HTML 頁面先通過負載均衡,再返回到用戶瀏覽器。頁面包含 Javascript 腳本和 CSS 資源文件,存於與咱們的 CDN 相連的雲端存儲系統中,用戶瀏覽器直接經過 CDN 獲取內容。最後,瀏覽器顯式地渲染頁面,供用戶瀏覽。
下面,咱們就每個組件詳細討論,作最最基礎的介紹,幫你建構認知模型,思考整個前面提到的整個網絡服務架構。以後我還會發布其它文章,基於在我司學習到的內容,爲你們更有針對性地從實踐角度作推薦。mysql
DNS(Domain Name Server)是域名服務器的簡稱,它是互聯網依存的基礎設施。簡單來講,DNS 提供域名與 IP 地址的鍵值對查找,例如(http://google.com 域名對應 85.129.83.120 IP 地址),這很是有必要,它讓你的電腦經過請求尋路到特定服務器。就比如打電話,域名與 IP 地址的關係相似於聯繫人和電話號碼的關係。之前你須要電話號碼簿記錄他人的電話號碼,如今你須要 DNS 服務器尋找域名對應的 IP 地址。因此你能夠把 DNS 想象成互聯網世界的電話簿。web
這裏咱們還有不少細節能夠深刻,暫時先跳過,由於這不是咱們基礎課的重點。算法
在詳解負載均衡以前,咱們先退一步討論一下應用的縱向擴展和橫向擴展。二者有什麼區別?簡單來講,參考 StackOverflow 的這篇帖子,橫向規模擴展意味着經過在資源池中加機器,縱向擴展意味着在已有機器上加強算力(如 CPU,RAM)。sql
在 web 開發絕大多數狀況下,會選擇橫向擴展。理由很簡單,服務器會宕機,網絡會斷線,數據中心會掉電。多臺服務器能夠保證你的應用在可以一邊停機維護,一邊持續工做。換句話說,應用可以「容錯」。另外,橫向擴展能最小限度地耦合不一樣後臺服務(web 服務器,數據庫,等等),使不一樣服務在不一樣機器上運行。還有一點,縱向擴展是有上限的,到達必定限度就沒法再擴展。世界上也不存在一臺超算計算機承載應用的全部計算,典型例子想象一下 Google 的搜索平臺,哪怕其它公司達不到這麼大的規模。其它公司,好比我司,Storyblocks,任什麼時候候都把服務跑在 150-400 個 AWS EC2 實例上。經過縱向擴展提供算力是至關有挑戰的。mongodb
回到負載均衡,能夠說它是橫向擴展的黑魔法。它將傳入請求轉路到多個服務器中的其中一個,再將響應回傳給客戶端。多個服務器彼此做爲鏡像,任意機器都會以一樣的方式處理請求。向服務集羣分發消息,便不會出現單個服務器過載的狀況。數據庫
理論上負載均衡就這些要點,很簡單直接。固然了,簡單的理論背後有更多細節,這篇入門文章裏咱們再也不贅述。apache
從上層角度來看,web 應用服務器相對好理解,它們用來處理核心業務邏輯,處理用戶請求,給客戶端瀏覽器返回 HTML。處理這些任務即是與後臺基礎設施間通訊,好比數據庫、緩存服務、任務隊列、搜索服務、其它微服務和消息/日誌隊列等等。通常狀況下至少兩個應用服務器,或者更多,這些應用服務接入負載均衡,處理用戶請求。瀏覽器
應用服務器的實現一般須要某種特定語言(Node.js, Ruby, PHP, Scala, Java, C# .NET 等)和對應的 MVC 框架上(Node.js 的 Express、Ruby on Rails、Scala 的 Play、PHP 的 Larave 和 Java 的 Spring 等等)。語言和框架的細節咱們這裏不作贅述,有興趣的讀者能夠自行深刻研究。
任意現代 Web 應用都使用一個甚至多個數據庫來存儲信息。數據庫用來定義數據結構,對數據進行增刪改查,高級運算操做等等。多數狀況下,web 應用服務器與一個數據庫進行直接通訊,任務服務器同理。另外,每一個後臺服務都有一個本身的數據庫,並與其它的應用隔離。
儘管在本文中,咱們儘可能避免深刻討論架構中的某個特定技術,這裏我仍是想特殊地提一下數據庫中的 SQL 和 NoSQL。
SQL(Structured Query Language)全稱結構化查詢語言,1970 年代發佈,提供了查詢關係型數據庫的一種標準形式,並廣爲大衆接受。SQL 數據庫將數據以表的形式存儲,經過 ID (一般爲 int 整型)這種方式使表之間相互關聯。舉個簡單的例子,咱們想要存儲用戶的歷史地址信息。須要準備兩張表,用戶表 users 和用戶地址表 user_addresses,並經過 user_id 進行關聯,以下圖。表間相關聯是經過在 user_addresses 表中使用 user_id 做爲外鍵實現的。
若是你不瞭解 SQL,這裏推薦可汗學院的課程學習。在 web 開發中 SQL 很是廣泛,瞭解其基礎做爲應用架構仍是頗有必要的。
NoSQL,如其字面意思,「非-SQL」,是一種新型數據庫,用來應對大規模 web 應用中的海量數據(大部分 SQL 不能很好支持橫向擴展,只能從某些方面支持縱向擴展)。若是你徹底不瞭解 NoSQL,推薦下列文章:
我還想順便提一點,業界一般使用 SQL 做爲 NoSQL 數據庫的表層調用,不懂 SQL 的話仍是頗有必要去學習的,現在的業務場景很難避開它。
緩存服務提供一種簡單的鍵值對數據存儲,使存取信息時間複雜度接近 O(1) 。應用內一般使用緩存服務存儲運算成本高昂的運算結果,再次請求時從緩存中檢索結果,而非在每次請求時都從新計算。緩存內容能夠是數據庫查詢,外部服務調用結果,連接返回的 HTML,等等。下面咱們從真實場景中舉例:
最經常使用到的服務器緩存技術是 Redis 和 Memcache。我以後會在其它文章中深刻討論。
大部分 web 應用背後都有異步任務在處理,這些任務沒必要直接響應用戶請求。好比說,谷歌須要爬取整個互聯網並創建索引以返回搜索結果,但這實際上並非在你每次搜索時都實時進行,而是經過異步方式爬取網絡結果並更新索引。
異步任務有不少不一樣的方式來完成,最經常使用的是任務隊列。它包含兩部分:正在運行的任務隊列,和一或多個處理任務的服務器(一般稱爲 workers)。
任務隊列存儲了一系列須要異步運行的任務。最簡單的任務調度是 FIFO(先進先出)的方式,不過大部分應用使用按優先級排序的調度方式處理任務。每當一個任務須要被執行,要麼使用統一的調度算法,要麼是按用戶行爲按需調度,該任務便被加入隊列中等待被執行。
舉個例子,我司利用任務隊列,賦能後臺任務以支持營銷活動。咱們用後臺任務編碼多媒體文件如視頻圖片,處理數據如在 CSV 作元數據標記,聚合用戶行爲分析,運行郵件服務好比給用戶發送重置密碼的郵件,等等。咱們最初使用 FIFO 調度任務,後來優化爲優先隊列,以保證時間敏感的操做完成的實時性,好比立馬發送重置密碼郵件。
任務服務器執行任務時,先查看任務隊列中是否有任務須要執行,如有任務便彈出該任務並執行。有不少語言和框架能夠在服務器上使用做爲任務隊列,這裏很少講。
在一些應用中,爲用戶提供搜索功能,用戶輸入文字時(查詢語句)應用返回相近結果。這種技術一般指的是「全文檢索」,運用倒排索引快速查找包含查詢關鍵字的文檔。
上圖中例子顯示了三個文檔標題被轉換成倒排索引,經過某些標題關鍵字可以快速檢索文檔。一般停用詞(英文中的:in、the、with 等,中文中:我、這、和、啊等)不會被加入到索引中。
儘管咱們能夠直接經過數據庫作全文檢索,好比 MySQL 支持全文檢索,但一般咱們會跑一個單獨的「搜索服務」計算並存儲倒排索引,並提供查詢接口。目前主流的全文檢索服務是 Elasticsearch,還有 Sphinx,Apache Solr 等選擇。
當應用到達必定的規模,一般傾向於拆分其爲單個應用,做爲「微服務」。外界對這些微服務是不可感知的,但應用內服務間相互通訊。好比我司有各類運維服務和計劃執行服務:
現在各大公司成敗在於 「如何很好地管理數據」,在應用到達必定規模時規範數據流程。通常來講有:加工數據、存儲數據和分析數據,這三個步驟:
還有一個步驟沒有在架構圖中繪出:從應用和服務運維數據庫中把數據導入數據倉庫。例如在我司,咱們每晚都會把各個服務的數據存到 AWS Redshift,把核心業務的數據和用戶交互行爲的數據放在一塊兒,提供給咱們的數據分析師一個總體化的數據集。
「雲存儲既簡單,擴展性又好,方便用戶在全網獲取、存儲、分享數據」 —— AWS 雲存儲服務。任意在本地文件系統存儲的文件,你均可以經過雲存儲存取,並用 HTTP 協議經過 RESTful API 訪問並交互。Amazon S3 提供了目前最流行的雲存儲,我司在其上普遍存儲各類東西,從多媒體素材、視頻、圖片、音頻,到 CSS、Javascript 乃至用戶行爲數據等等。
CDN 指的是內容分發網絡,該技術提供一種素材服務,好比存儲靜態 HTML,CSS,Javascript 和圖片。從全網獲取這些靜態素材比從單個源服務器獲取要快的多。它的工做原理是將內容分佈在世界各地的邊緣服務器上,而不是僅僅放在一個源節點上。好比說,下圖中一個西班牙的用戶訪問某個源節點位於紐約的網站,可是頁面的靜態素材經過英國的 CDN 邊緣服務器載入,這樣就避免了冗餘的跨大西洋的 HTTP 請求,提快了訪問速度。
這篇文章 更詳細解釋了爲何使用 CDN。總的來講,網絡應用可使用 CDN 來存儲諸如 CSS、Javascript 和圖片視頻等素材,甚至靜態 HTML 網頁。
以上即是網絡應用架構基礎課的所有內容,但願這篇文章對你有幫助。接下來我還會發布進階課的文章,詳細研究上述的某些組件。