一個(gè)Web項(xiàng)目, 可大可小, 大到整個(gè)阿里巴巴, 小到你自己的博客, 留言板. 雖然所采用的技術(shù)不一樣, 規(guī)模不一樣, 但是都由一些執(zhí)行相同作用的組件所構(gòu)成的, 當(dāng)然根據(jù)規(guī)模的不同, 要實(shí)現(xiàn)的功能的不同, 有一些組件并不一定是必須, 但是當(dāng)一個(gè)項(xiàng)目從小到大的演變過程中, 需要加入的組件都是大致功能類似的. 下面我們就從最簡單的Web項(xiàng)目開始, 到隨著功能, 規(guī)模的遞增, 看看有那些組件需要加入, 和各自的作用.
1. 種子規(guī)模
這個(gè)規(guī)模的項(xiàng)目最好的實(shí)例就是個(gè)人博客, 留言板, 公司介紹網(wǎng)站等, 基本結(jié)構(gòu)如下
這是最簡單的模式, 基本上可以概括為 ?請求-響應(yīng) 模式. 主要的組件是由Web框架 和 數(shù)據(jù)庫兩個(gè)部分組成, Web框架負(fù)責(zé)為開發(fā)者提供基礎(chǔ)的應(yīng)用程序結(jié)構(gòu)和功能: 1. 接收HTTP請求 2.渲染返回的HTML頁面, 數(shù)據(jù)庫則負(fù)責(zé)持久化數(shù)據(jù): 比如留言的內(nèi)容.
隨著使用人數(shù)的上升, 性能很快入不敷出, 你開始覺得訪問的時(shí)候速度不如原來快了. 但是你在用top命令查看系統(tǒng)開銷的時(shí)候會(huì)發(fā)現(xiàn), 其實(shí)系統(tǒng)的CPU占用并不是很高. 原來這個(gè)時(shí)候大部分的時(shí)候CPU都在等帶數(shù)據(jù)庫查詢的結(jié)果, 而數(shù)據(jù)庫查詢結(jié)果很多時(shí)候是重復(fù)的, 比如當(dāng)沒有人留言的時(shí)候, 返回的最新留言列表. 為了避免無謂的IO開銷, 我們需要用一個(gè)比數(shù)據(jù)庫快N倍的存儲(chǔ)設(shè)備來緩存查詢的結(jié)果, 這樣當(dāng)我們發(fā)現(xiàn)查詢結(jié)果不會(huì)有變化的時(shí)候, 就能通過更快的存儲(chǔ)設(shè)備拿到結(jié)果, 比如內(nèi)存就是用戶級(jí)應(yīng)用程序能訪問的最快, 而且現(xiàn)在看來容量也夠大(將來會(huì)越來越大)的存儲(chǔ)設(shè)備了. 這個(gè)時(shí)候我們需要引入一個(gè)新的組件: 內(nèi)存緩存
2. 發(fā)芽規(guī)模(開始擴(kuò)展了)
引入緩存后, 項(xiàng)目的基本結(jié)構(gòu)如下圖所示:
目前最常用的內(nèi)存緩存基本上就MemoryCache和Redis兩個(gè)了, MemoryCache就是個(gè)單存的內(nèi)存緩存, 而Redis不光快, 還是個(gè)啥都能干的萬金油, 你可以將其視作為一個(gè)在線內(nèi)存數(shù)據(jù)結(jié)構(gòu)服務(wù), 除了KV之外還提供了SET, List, Hash等多種數(shù)據(jù)結(jié)構(gòu), 功能太強(qiáng)我們后面還會(huì)提到詳細(xì)說.
緩存大體上有兩種使用的方式, 一種是輸出緩存, 另一種是數(shù)據(jù)緩存.
輸出緩存是作用在Web框架輸出端, 基本的作用過程是這樣子的.
當(dāng)讀取的頻率大于寫入或者更新的時(shí)候, 輸出緩存能夠很大程度上的提升性能, 因?yàn)榇蟛糠衷拘枰ㄟ^數(shù)據(jù)庫去獲取的數(shù)據(jù)直接通過內(nèi)存獲得了, 而內(nèi)存的速度是數(shù)據(jù)庫的N倍, 所以系統(tǒng)的容量能夠成倍的增長.
但是, 如果輸出的內(nèi)容需要在數(shù)據(jù)的基礎(chǔ)上做一些處理, 比如返回了留言列表, 但是要根據(jù)和當(dāng)前日期的比對(duì)顯示留言的時(shí)間, 最近的幾條顯示諸如: 剛剛, 1分鐘前, 半小時(shí)前... 等. 隨著時(shí)間的變動(dòng), 返回的留言沒變, 但是留言時(shí)間的顯示需要變化, 那么這個(gè)時(shí)候輸出緩存就無能為力了, 我們需要數(shù)據(jù)緩存來滿足需求.
數(shù)據(jù)緩存的執(zhí)行邏輯如下圖所示:
但是這兩種緩存模式都是在項(xiàng)目中根據(jù)需要來使用, 大多數(shù)時(shí)候一個(gè)項(xiàng)目中兩種模式都會(huì)存在.在實(shí)際的項(xiàng)目中緩存并非只有自建一種選擇, 還有客戶端緩存和CDN之類的緩存形式, 我們在緩存的部分專門展開來詳細(xì)介紹.
隨著規(guī)模的增長, 功能的增加, 有的時(shí)候我們需要在項(xiàng)目中增加一些很耗時(shí)的操作, 比如上傳了視頻后需要壓縮視頻等操作, 會(huì)產(chǎn)生大量的IO等待, 又比如一些匯總查詢, 都是很耗時(shí)的操作, 這個(gè)時(shí)候我們就需要將這些操作放到別的進(jìn)程去執(zhí)行, 那么就又需要加入兩個(gè)新的組件: 消息總線和任務(wù)服務(wù).
3.小苗規(guī)模
這個(gè)階段呢, 有一些需求會(huì)需要訪問慢IO, 或者產(chǎn)生高CPU運(yùn)算的任務(wù), 會(huì)嚴(yán)重影響系統(tǒng)的吞吐量. 這個(gè)時(shí)候我們需要充分的運(yùn)用多核CPU的優(yōu)勢, 將耗時(shí)的工作交給別的CPU去搞定, 所以需要一個(gè)進(jìn)程管理器來管理一組進(jìn)程來專門接收-執(zhí)行這些任務(wù), 而為了通知這些進(jìn)程來獲取要執(zhí)行任務(wù)的數(shù)據(jù), 需要消息總線來負(fù)責(zé)在Web應(yīng)用和進(jìn)程管理器之間來傳遞消息.?
加上這兩個(gè)組件后, 項(xiàng)目的結(jié)構(gòu)變成了這樣子:
在這個(gè)階段, 我們已經(jīng)可以精細(xì)的將不同開銷的任務(wù)解藕開, 將高開銷, 高耗時(shí)的邏輯從Web的主進(jìn)程中剝離出來, 從而滿足進(jìn)一步擴(kuò)大系統(tǒng)吞吐量的目的.
而消息服務(wù)的引入進(jìn)一步擴(kuò)展了系統(tǒng)的彈性, 我們可以將不同的功能分解成獨(dú)立的服務(wù), 各自通過消息服務(wù)整合起來, 從而實(shí)現(xiàn)了整個(gè)系統(tǒng)的微服務(wù)化.
在這個(gè)結(jié)構(gòu)下, 一個(gè)開銷很大的請求的執(zhí)行過程如下:
在這個(gè)階段, 各個(gè)模塊已經(jīng)實(shí)現(xiàn)了基本上的解藕, 無論是功能或者容量上的擴(kuò)展都比較方便了, 所以接下來的目標(biāo)就是針對(duì)一個(gè)特殊的需求添加必要的組件了
4. 小樹規(guī)模(生長枝條)
演變到這個(gè)階段, 系統(tǒng)的大體模型已經(jīng)固定下來了, 生下來的是根據(jù)不同的需要添加一些特殊的組件了.結(jié)構(gòu)如下:
4.1 全文檢索
在傳統(tǒng)的關(guān)系型數(shù)據(jù)庫中, 類似 Like '% 張三 %' 這類的查詢都是會(huì)丟失索引, 所以類似這樣的查詢只有通過全文檢索引擎來搜索才能有足夠的效率, 在互聯(lián)網(wǎng)領(lǐng)域用得最多的MySQL在全文檢索方面的功能太過于孱弱, 所以現(xiàn)在而今眼目下業(yè)內(nèi)大多用Solr, Elasticsearch等全文檢索引擎來提供全文檢索服務(wù). 如果你是PostgreSQL黨的話就會(huì)省心很多, 數(shù)據(jù)庫自帶的Gist, Gin, Brin這些類型的索引都能提供很好的全文檢索能力.
4.2 日志系統(tǒng)(收集+存儲(chǔ)+檢索)
當(dāng)整個(gè)系統(tǒng)都微服務(wù)化后, 服務(wù)進(jìn)程數(shù)量很多, 且會(huì)分布在不同的主機(jī)上, 這個(gè)時(shí)候再將日志寫到本地磁盤上, 采集整理日志會(huì)非常的痛苦, 所以需要統(tǒng)一的日志系統(tǒng)來處理系統(tǒng)日志.
一般的日志系統(tǒng)都是由 前端采集器 - 采集對(duì)列 - 寫入器 三個(gè)部分構(gòu)成, 數(shù)據(jù)存儲(chǔ)基本上都由全文檢索引擎來搞定了, 這樣方便了后續(xù)對(duì)日志的處理.
4.3 LBS索引
在傳統(tǒng)的關(guān)系型數(shù)據(jù)庫中沒有Gist索引, 所以沒有辦法對(duì)經(jīng)緯度等數(shù)據(jù)進(jìn)行索引, 所以需要單獨(dú)的LBS索引服務(wù). 當(dāng)然對(duì)于PostgreSQL來說并沒有這個(gè)必要.
4.4 OLAP數(shù)據(jù)倉庫(數(shù)據(jù)分析)
我們常用的MySQL, PostgreSQL都是OLTP型的關(guān)系型數(shù)據(jù)庫, 也就是針對(duì)聯(lián)機(jī)事務(wù)處理優(yōu)化模式工作的數(shù)據(jù)庫, 俗話說就是針對(duì) 增刪改查等操作專門優(yōu)化, 跑起來傻快傻快的, 但是對(duì)于要做匯總查詢之類的就速度上不行了. 如果要對(duì)數(shù)據(jù)進(jìn)行專門的挖掘鉆取的話, 需要把數(shù)據(jù)存入專門對(duì)數(shù)據(jù)分析優(yōu)化的OLAP類型的數(shù)據(jù)倉庫中. 術(shù)業(yè)有專攻, 這個(gè)領(lǐng)域不是強(qiáng)項(xiàng)所以簡略帶過, 后面有機(jī)會(huì)再詳細(xì)說
以上所有的服務(wù)我們在后面都有相應(yīng)的主題來詳細(xì)描述, 這里就簡略帶過了.
5. 大樹規(guī)模(群集化, 超大規(guī)模)
在這個(gè)階段, 結(jié)構(gòu)得到了充分的展開, 每一個(gè)組件充分的解藕, 就能夠根據(jù)具體的系統(tǒng)負(fù)載來針對(duì)特定的瓶頸來優(yōu)化, 擴(kuò)容, 升級(jí). 這個(gè)時(shí)候并沒有一個(gè)固定的模式了, 不同的業(yè)務(wù)需求, 不同的數(shù)據(jù)類型都會(huì)造成在這個(gè)階段的需求是不一樣的, 結(jié)構(gòu)也是不一樣的, 所以我們會(huì)單獨(dú)拿一個(gè)主題來詳細(xì)說明.
下一節(jié)主題: Web框架如何快速入門
to be continue...