經(jīng)驗分享:資深架構(gòu)師教你什么是網(wǎng)絡(luò)應(yīng)用架構(gòu)?
導(dǎo)讀:本文作者基于其公司 (StoryBlock) 的實際業(yè)務(wù)架構(gòu)向我們分享了一節(jié)生動詳細(xì)的網(wǎng)絡(luò)架構(gòu)入門課,雖然作者的預(yù)期閱讀對象是前端開發(fā)人員,但是也非常適合產(chǎn)品經(jīng)理閱讀和學(xué)習(xí),尤其是已經(jīng)有一定工作經(jīng)驗的產(chǎn)品經(jīng)理,希望對大家有用。
01 從一個場景開始
以上的架構(gòu)圖是對 Storyblocks 業(yè)務(wù)架構(gòu)的一個很好的概括。對于那些相對缺乏經(jīng)驗的 web 開發(fā)者,或許你會覺得這個架構(gòu)有些復(fù)雜。沒關(guān)系,在講解相關(guān)組件的具體業(yè)務(wù)細(xì)節(jié)之前,我們先舉個例子,幫你更容易地理解 Storyblocks 的業(yè)務(wù)架構(gòu)。
先從一個場景開始:用戶用谷歌搜索 「美麗的濃霧和林間的陽光」 。首個結(jié)果正好出自 Storyblocks:一個知名的圖片和矢量圖資源網(wǎng)站,用戶點擊該條結(jié)果,瀏覽器重定向到該圖片的所在的詳情頁面。
這個場景背后,用戶瀏覽器向 DNS 服務(wù)器發(fā)送請求,查詢 Storyblocks 的域名信息,然后發(fā)送訪問請求。訪問請求首先經(jīng)過負(fù)載均衡器,負(fù)載均衡器會從十多臺運行網(wǎng)站服務(wù)的網(wǎng)絡(luò)服務(wù)器選擇任意一臺,將請求發(fā)送到這臺服務(wù)器進(jìn)行處理,網(wǎng)絡(luò)服務(wù)器先從緩存服務(wù)器查詢圖片的詳情信息,然后從數(shù)據(jù)庫獲取圖片的其他相關(guān)信息。
我們注意到這張圖片的色彩配置信息還沒被計算出來,于是服務(wù)器將一個新的色彩配置任務(wù)推送到任務(wù)隊列,我們的任務(wù)隊列服務(wù)器將異步地處理圖片的色彩配置信息計算,一旦計算完成,便將配置信息更新到數(shù)據(jù)庫中。
下一步,服務(wù)器將圖片標(biāo)題作為關(guān)鍵詞,向全文檢索服務(wù)發(fā)送查詢請求以尋找相似圖片。此時用戶登入他的 Storyblocks 賬戶,相應(yīng)地,服務(wù)器從賬戶服務(wù)中獲取用戶賬戶信息。
接下來,我們將這個頁面瀏覽事件加載到 data firehose(AWS 推出的流數(shù)據(jù)裝載服務(wù)) 以記錄到云存儲系統(tǒng),并最終存儲到數(shù)據(jù)倉庫,便于分析師分析使用并幫助解答業(yè)務(wù)問題。
服務(wù)端將視圖呈現(xiàn)為為 HTML 頁面并經(jīng)由負(fù)載均衡器,返回用戶的瀏覽器客戶端。這個頁面同時包含存儲在云存儲系統(tǒng)的 Javascript 和 CSS 代碼文件,云服務(wù)器直接連接到 CDN 集群,內(nèi)容也經(jīng)由 CDN 分發(fā),用戶瀏覽器訪問 CDN 集群并獲取內(nèi)容。
最終,瀏覽器渲染頁面使用戶可以瀏覽閱讀。
接下來,我將帶你遍歷每個組件,并做簡要說明和介紹,幫助你形成一個相對準(zhǔn)確的概念模型,以便于理解網(wǎng)絡(luò)架構(gòu)和組件間的交互。我仍將遵循已經(jīng)分享的文章中給出的一些實踐建議,這些建議基于我在 Stroyblocks 的業(yè)務(wù)經(jīng)驗,具有一定參考價值。
02 網(wǎng)絡(luò)架構(gòu)諸組件
1. DNS 服務(wù)
DNS (Domain Name System)代表 「域名系統(tǒng)」,這是實現(xiàn)互聯(lián)網(wǎng)相互連接的核心技術(shù)。DNS提供從域名 (例如 google.com) 到 IP 地址 (85.129.83.120) 的最底層的鍵值對查詢服務(wù),事實上,計算機(jī)基于網(wǎng)站的 IP 地址路由到合適的服務(wù)器。用電話號碼比喻的話:域名和 IP 地址的關(guān)系,類似于聯(lián)系人姓名和號碼的關(guān)系。
正如你需要通過電話簿來查詢特定聯(lián)系人的電話號碼,你同樣需要通過 DNS 來查詢指定域名的 IP 地址,所以你完全可以把 DNS 理解為互聯(lián)網(wǎng)的電話號碼簿。
我們以后會深入介紹關(guān)于 DNS 的詳細(xì)原理,現(xiàn)在進(jìn)入下一個話題。
2. 負(fù)載均衡
在深入介紹負(fù)載均衡之前,我們需要先行解釋應(yīng)用架構(gòu)的水平拓展和垂直拓展。
你肯定會好奇這兩個概念的含義和區(qū)別:簡單來說,水平拓展是指你向資源池增加更多機(jī)器設(shè)備,而垂直拓展則意味著增加更多算力資源(CPU,內(nèi)存)到現(xiàn)有機(jī)器設(shè)備。對于 Web 開發(fā),水平拓展常常是最好的選擇。
畢竟,所有事物都可能中斷,服務(wù)器有時崩潰,網(wǎng)絡(luò)會降速,甚至整個數(shù)據(jù)中心也會偶爾斷線。如果要防止出錯,除了保持簡單,我們別無選擇。使用服務(wù)器集群可以幫你有效應(yīng)對突發(fā)情況,增強(qiáng)業(yè)務(wù)的健壯性和容錯性,確保應(yīng)用持續(xù)穩(wěn)定地運行。
其次,水平拓展允許你將后端服務(wù) (網(wǎng)絡(luò)服務(wù)器,數(shù)據(jù)庫,應(yīng)用服務(wù)) 的不同組件分配在不同服務(wù)器,借此你可以高效地調(diào)用后端服務(wù)的不同組件。
最后,垂直拓展很容易遇到規(guī)模瓶頸,谷歌的搜索服務(wù)平臺是一個相當(dāng)?shù)湫偷陌咐?,這個場景也同時適用于 Storyblocks 這樣的中小型公司,舉例來說,我們在任意時刻都運行著 150 到 400 個 AWS EC2 實例,如果要通過垂直拓展模式提供同等算力,很難想象我們需要使用何種級別和規(guī)模的計算機(jī)設(shè)備(估計得使用超算了)。
現(xiàn)在我們回到負(fù)載均衡器,它們是實現(xiàn)業(yè)務(wù)水平拓展的重要部分,它們將接收的訪問請求路由到互為備份的應(yīng)用服務(wù)器集群中的任意一個,并將應(yīng)用服務(wù)器的響應(yīng)返回到客戶端。任何一個應(yīng)用服務(wù)器的處理方式都完全相同,通過這種方式,負(fù)載均衡器將訪問請求均勻地分派到不同的服務(wù)器以防止服務(wù)器過載。
負(fù)載均衡器的業(yè)務(wù)原理相當(dāng)簡單,但是要深入理解,就涉及到很多復(fù)雜的概念,這些更加復(fù)雜的概念,我們將在以后進(jìn)行講解。
3. Web 應(yīng)用服務(wù)器
從抽象角度來說,Web 應(yīng)用服務(wù)器的作用是這樣的:它們被用來執(zhí)行諸如處理用戶請求和將 HTML 返回用戶瀏覽器等核心業(yè)務(wù)邏輯。為了確保任務(wù)完成,應(yīng)用服務(wù)器通常會和數(shù)據(jù)庫,緩存層,任務(wù)隊列,搜索服務(wù),其他微服務(wù)組件,數(shù)據(jù)/日志隊列等一系列后端基礎(chǔ)設(shè)施交互。
正如上文所提及,很多時候,由于負(fù)載均衡器的存在,應(yīng)用服務(wù)器需要成倍地連接更多服務(wù),以便于處理大規(guī)模的用戶訪問請求。
應(yīng)用服務(wù)的技術(shù)實現(xiàn)首先基于特定后端語言,如 Node.js, Ruby, Scala, Java, C#, .NET 等等,同時需要選擇基于該后端語言的 Web MVC 框架,如 Express 之于 Node.js, Ruby on Rails, Play 之于 Scala, Laravel 之于 PHP 等等。本文僅做基本介紹,不會過于深入介紹這些語言和框架的具體實現(xiàn)細(xì)節(jié)。
4. 數(shù)據(jù)庫服務(wù)器
任何一個現(xiàn)代的 Web 應(yīng)用都使用一個或以上的數(shù)據(jù)庫存儲信息。數(shù)據(jù)庫幫助我們完成諸如定義數(shù)據(jù)結(jié)構(gòu),插入數(shù)據(jù),查找數(shù)據(jù),更新和刪除數(shù)據(jù),以及執(zhí)行數(shù)據(jù)計算等各種數(shù)據(jù)庫操作。
在大多數(shù)情況下,Web 應(yīng)用服務(wù)器和專有的數(shù)據(jù)庫服務(wù)器直接通信,對于任務(wù)服務(wù)器也是如此。另外,任何一個后端服務(wù)都可能擁有一個獨立于其他應(yīng)用的專有服務(wù)器。
盡管我在試圖避免在每個組件上過于深入細(xì)節(jié),但是如果我不詳細(xì)解釋數(shù)據(jù)庫的一些基礎(chǔ)概念,(SQL 和 NoSQL),必將會影響你理解接下來的其他概念。
SQL(Structured Query Language, SQL),代表 「結(jié)構(gòu)化查詢語言」。被發(fā)明于上世紀(jì)七十年代,作為標(biāo)準(zhǔn)的關(guān)系數(shù)據(jù)庫數(shù)據(jù)查詢方式,最終被廣泛接受和使用。SQL 數(shù)據(jù)庫將數(shù)據(jù)存儲在數(shù)據(jù)表中,通過 ID 等字段進(jìn)行表關(guān)聯(lián)。
舉一個簡單的存儲用戶歷史地址信息的的例子簡要說明:現(xiàn)有兩個表:【用戶表: users】和【用戶地址表: user_addresses】,這兩張表通過用戶編號相關(guān)互聯(lián),如下圖所示。這些表相互關(guān)聯(lián),是因為【用戶地址表】的 {用戶編號: id} 信息是用戶表中 {用戶編號: id} 在用戶地址表的外鍵 (Foreign Key, FK)。
如果你對 SQL 不太了解,我強(qiáng)烈建議你學(xué)習(xí)這個基礎(chǔ)教程,可汗學(xué)院的 SQL 入門課:數(shù)據(jù)查詢與數(shù)據(jù)管理 ,SQL 在 Web 開發(fā)領(lǐng)域應(yīng)用相當(dāng)廣泛,你至少需要了解基礎(chǔ)知識,這樣才能恰當(dāng)?shù)卦O(shè)計應(yīng)用架構(gòu)。
NoSQL 代表 Non-SQL 或 Not-Only-SQL,是指新一代的數(shù)據(jù)庫技術(shù),用于處理大型網(wǎng)絡(luò)應(yīng)用所產(chǎn)生的巨量數(shù)據(jù)(大多數(shù)關(guān)系型數(shù)據(jù)庫無法很好地水平拓展,只能垂直拓展,直到性能瓶頸)。如果你對 NoSQL 一無所知,我建議你從以下介紹入手:
- https://www.w3resource.com/mongodb/nosql.php
- http://www.kdnuggets.com/2016/07/seven-steps-understanding-nosql-databases.html
- https://resources.mongodb.com/getting-started-with-mongodb/back-to-basics-1-introduction-to-nosql
值得注意的是,基于 SQL 查詢已經(jīng)成為數(shù)據(jù)庫的通行接口標(biāo)準(zhǔn),即使對于 NoSQL 數(shù)據(jù)庫也是如此。所以如果你對 SQL 缺乏了解,很有必要認(rèn)真學(xué)習(xí)一番,在互聯(lián)網(wǎng)行業(yè),SQL 是無可避免的。
5. 緩存服務(wù)
緩存服務(wù)為相關(guān)信息提供簡單的鍵值數(shù)據(jù)存儲,可在接近 O(1) 時間內(nèi)保存和查找信息。
O(1) 是指算法的時間復(fù)雜度為常數(shù)階,換言之,此場景下,任何單次查詢的時間都是相對穩(wěn)定的,和該條查詢指令復(fù)雜度基本無關(guān)。
應(yīng)用服務(wù)同樣會利用緩存服務(wù)預(yù)先存儲一些計算量較大的計算結(jié)果,以便于下次需要時直接從緩存中獲取結(jié)果而重新計算。應(yīng)用服務(wù)也可能從其他服務(wù)獲取緩存,如數(shù)據(jù)庫查詢結(jié)果,外部服務(wù)調(diào)用結(jié)果,指定URL 的 HTML 文件,以及其他服務(wù)。下面是真實世界的一些案例:
- 谷歌直接緩存常見的搜索關(guān)鍵詞如「狗」或者「泰勒·斯威夫特」的搜索結(jié)果,而非搜索時重新計算。
- Facebook 緩存你登入賬戶時所看到的信息,如你的發(fā)帖記錄信息和朋友列表信息等數(shù)據(jù)。這篇文章詳細(xì)介紹了 Facebook 的緩存技術(shù)應(yīng)用。
- Storyblocks 緩存服務(wù)端的 React 渲染生成的HTML 文件,搜索結(jié)果和提前輸入結(jié)果等信息
使用最廣泛的兩種緩存服務(wù)器技術(shù)是 Redis 和 Memcache,后續(xù)也會針對這兩種技術(shù)進(jìn)行介紹。
6. 任務(wù)隊列和服務(wù)器
在不涉及于用戶交互的場景中,網(wǎng)絡(luò)應(yīng)用需要異步地完成很多工作。例如,為了搜索查詢結(jié)果,谷歌需要用爬蟲遍歷全網(wǎng)的內(nèi)容并編制索引,谷歌不是在用戶搜索時才進(jìn)行上述操作,相反,它異步地爬取網(wǎng)絡(luò)內(nèi)容,并預(yù)先更新查詢索引。
盡管有很多應(yīng)用架構(gòu)可用于完成異步任務(wù),但最通用的是「任務(wù)隊列架構(gòu) (Job Quene)」。它包括兩個組件:一系列等待被執(zhí)行的「任務(wù)」和數(shù)個用于執(zhí)行任務(wù)的任務(wù)服務(wù)器(通常被稱為 Workers )
任務(wù)隊列存儲一系列需要被異步執(zhí)行的任務(wù)。先進(jìn)先出(First In First Out, FIFO)隊列是最簡單的任務(wù)隊列,盡管多數(shù)應(yīng)用最終需要可以按照優(yōu)先級排序的隊列系統(tǒng)。不管是由日常任務(wù)調(diào)度安排或是由用戶操作觸發(fā),一旦應(yīng)用服務(wù)需要執(zhí)行任務(wù),它都會將合適的任務(wù)添加到隊列中。
例如,Storyblocks,將任務(wù)隊列用于強(qiáng)化那些用于支持市場的幕后工作:例如視頻和圖片的編碼,包含元數(shù)據(jù)標(biāo)簽的 CSV 的處理,用戶統(tǒng)計數(shù)據(jù)的聚合,密碼重置郵件的發(fā)送等任務(wù)。起初我們使用簡單的 FIFO 隊列,但最終我們還是升級為優(yōu)先級列隊以確保那些時間敏感的任務(wù)可以迅速完成(如密碼重置郵件的發(fā)送)
任務(wù)服務(wù)器的任務(wù)處理流程為:任務(wù)服務(wù)器輪詢?nèi)蝿?wù)隊列以確定是否有任務(wù)需要執(zhí)行,如有則推出(pop)該任務(wù)并加以執(zhí)行。相關(guān)的編程語言和服務(wù)框架數(shù)不勝數(shù),這里就不作過多展開。
7. 全文檢索服務(wù)
當(dāng)用戶輸入文字進(jìn)行查詢時,多數(shù)網(wǎng)絡(luò)應(yīng)用都或多或少地提供檢索功能,應(yīng)用服務(wù)返回最相關(guān)的查詢結(jié)果。這種用于支持文本查詢的功能,通常被稱為「全文檢索」,全文檢索使用反向索引以便快速查詢包含關(guān)鍵詞的文件信息。
上圖說明如何將這三個文檔標(biāo)題轉(zhuǎn)換為反向索引,以便于從特定關(guān)鍵字快速查找到標(biāo)題中具有該關(guān)鍵字的文檔。請注意,如 “in”,”with” 等常見單詞,通常不包括在倒置索引中的常見單詞(被稱為停止詞: stop words)
盡管有些數(shù)據(jù)庫直接提供全文檢索特性(例如,MySQL 支持全文搜索)但將一般將計算生成并存儲反向索引的「檢索服務(wù)」作為獨立服務(wù)并提供查詢接口?,F(xiàn)在最流行的全文檢索平臺是 Elasticsearch,同時 Sphinx 和 Apache Solr 也是常見的備用選擇。
8. 服務(wù)
當(dāng)應(yīng)用達(dá)到一定規(guī)模,其中有些服務(wù)需要拆分出來成為單獨的應(yīng)用。這些新應(yīng)用不一定用于開放給外部系統(tǒng),但是一定會用于和原應(yīng)用以及其他服務(wù)交互。舉例來說,Storyblocks 有以下幾種操作和計劃服務(wù):
- 賬戶服務(wù):存儲用戶在我們所有站點的相關(guān)數(shù)據(jù),這將有助于我們提供交叉銷售的機(jī)會并創(chuàng)造統(tǒng)一的用戶體驗
- 內(nèi)容服務(wù):存儲所有視頻、音頻和圖形內(nèi)容的元數(shù)據(jù),同時為內(nèi)容下載和查看下載歷史記錄提供接口
- 支付服務(wù):為處理客戶信用卡結(jié)算信息提供接口
- HTML → PDF 服務(wù): 提供簡單的處理接口,以支持根據(jù) HTML 頁面返回相應(yīng) PDF 文件
9. 數(shù)據(jù)處理
大數(shù)據(jù)時代,公司的生死存亡系于對數(shù)據(jù)的完善利用程度。現(xiàn)在的網(wǎng)絡(luò)應(yīng)用,只要達(dá)到一定業(yè)務(wù)規(guī)模,就一定會建立數(shù)據(jù)管道以確保數(shù)據(jù)的收集、存儲和分析。典型的數(shù)據(jù)管道包括以下三個主要過程:
- 數(shù)據(jù)流處理:應(yīng)用發(fā)送數(shù)據(jù),特別是關(guān)于用戶行為的事件信息,到 data firehose,后者提供了流處理接口以攝取和處理數(shù)據(jù)。通常來說,源數(shù)據(jù)會經(jīng)過轉(zhuǎn)換或處理并發(fā)送到另外的 firehose。AWS Kinesis 和 Kafka 是用于此目的的兩種最常見的技術(shù)
- 數(shù)據(jù)云存儲:源數(shù)據(jù)以及經(jīng)過轉(zhuǎn)換或處理的新數(shù)據(jù)將被存儲到云存儲系統(tǒng)。AWS Kinesis 提供了一種名為 “firehose” 的設(shè)置,它幫助我們輕松地配置將源數(shù)據(jù)存儲到云存儲 (AWS S3) 的整個過程
- 同步到數(shù)據(jù)倉庫:經(jīng)過轉(zhuǎn)換或處理的新數(shù)據(jù)常常被裝載到數(shù)據(jù)倉庫以便于分析。我們也使用 AWS Redshift,它在創(chuàng)業(yè)公司中相當(dāng)普遍且份額正逐漸擴(kuò)大。盡管大公司通常使用 Oracle 或其他專有的數(shù)據(jù)倉庫技術(shù)。如果數(shù)據(jù)集足夠龐大,對于分析而言,類 Hadoop 的 NoSQL MapReduce 技術(shù)將是必要的。
應(yīng)用架構(gòu)圖中未提及的一個環(huán)節(jié)是:將數(shù)據(jù)從網(wǎng)絡(luò)應(yīng)用和服務(wù)的生產(chǎn)數(shù)據(jù)庫裝載到數(shù)據(jù)倉庫。比如在 Storyblocks 我們每天裝載視頻塊,音頻塊,故事塊(VideoBlocks, AudioBlocks, Storyblocks)和賬戶服務(wù)以及參與者門戶數(shù)據(jù)庫到 RedShift。由此通過整合核心業(yè)務(wù)數(shù)據(jù)和用戶行為事件數(shù)據(jù),為數(shù)據(jù)分析師提供完整的數(shù)據(jù)集。
10. 云存儲
按照 AWS 的說法,「云存儲是一種存儲、訪問和分享數(shù)據(jù)的方便且可拓展的方式」
和本地文件系統(tǒng)的現(xiàn)有方式一樣,你可以使用云存儲來存儲和訪問任何文件,其好處是能夠調(diào)用 RESTful API 通HTTP 交互。到目前為止,亞馬遜 S3 是市場上最受歡迎的云存儲服務(wù)(國內(nèi)則是阿里云),也被 Storyblocks 用于存儲視頻、圖片和音頻資源,還有 CSS 和 Javascript 代碼,以及用戶事件數(shù)據(jù)等信息。
11.CDN
CDN(Content Delivery Network)代表「內(nèi)容分發(fā)網(wǎng)絡(luò)」,該技術(shù)提供了一種快速加載 HTML、CSS、JavaScript 文件和圖片等網(wǎng)頁資源的方式,這比從原服務(wù)器直接請求要要快得多。
CDN 基于遍布世界各地的「邊緣服務(wù)器 (Edge Server)」分發(fā)內(nèi)容,這樣用戶可以從邊緣服務(wù)器加載網(wǎng)頁資源,而不用訪問原服務(wù)器加載。如下圖所示:身在西班牙的用戶請求原站點位于美國紐約的網(wǎng)頁,但是靜態(tài)網(wǎng)絡(luò)資源卻經(jīng)由CDN 網(wǎng)絡(luò)中位于英國的邊緣服務(wù)器獲取,而非通過緩慢且不安全的跨洋 HTTP 請求。
想要了解更詳盡的介紹,可以查看本文。通常來說,Web 應(yīng)用應(yīng)始終使用 CDN 為 CSS、Javascript、圖像、視頻和任何其他網(wǎng)絡(luò)資源提供服務(wù)。某些應(yīng)用還會使用 CDN 來分發(fā)靜態(tài) HTML 頁面。
寫在最后
文章作者基于其公司 (StoryBlock) 的實際業(yè)務(wù)架構(gòu)向我們分享了一節(jié)生動詳細(xì)的網(wǎng)絡(luò)架構(gòu)入門課,雖然作者的預(yù)期閱讀對象是前端開發(fā)人員,但是也非常適合產(chǎn)品經(jīng)理閱讀和學(xué)習(xí),尤其是已經(jīng)有一定工作經(jīng)驗的產(chǎn)品經(jīng)理。
畢竟,我們所設(shè)計的產(chǎn)品最終通過互聯(lián)網(wǎng)分發(fā)給全國和世界各地的用戶,我們對于互聯(lián)網(wǎng)通信過程了解越深入,就越有可能發(fā)現(xiàn)產(chǎn)品所可能存在的缺陷和問題,也就越有可能做出真正優(yōu)秀的產(chǎn)品。
希望各位讀者能夠有所收獲,我也將陸續(xù)創(chuàng)作和翻譯其他相關(guān)產(chǎn)品和技術(shù)的內(nèi)容和分享。
原文地址:?web-architecture-101
本文由 @遍歷分形 翻譯發(fā)布于人人都是產(chǎn)品經(jīng)理,未經(jīng)作者許可,禁止轉(zhuǎn)載。
題圖來自Unsplash,基于CC0協(xié)議。
- 目前還沒評論,等你發(fā)揮!