服務架構(gòu)簡介:你是否了解這些常用架構(gòu)?
我們?nèi)粘I钪惺褂煤芏鄳贸绦颍形⑿拧⒍兑簟⑼跽哌@種涉及多人聯(lián)網(wǎng)互動的大型應用,它們以操作系統(tǒng)作為宿主;也有網(wǎng)站、小程序、PWA等借殼的應用。面向用戶表現(xiàn)為Android/iOS/Windows/MacOS/瀏覽器/H5/Terminal 等端上的應用程序,名為 Client。更多情況下,業(yè)務的核心邏輯體現(xiàn)在背后看不見的服務,名為 Server。
從普通用戶視角跳出來,切換到程序員視角,應用程序可以理解為是M個Client和N個Server的組合。在軟件開發(fā)過程中,Client/Server的邊界如何劃分,Server之間如何通信,多個Server如何組織能夠保證整個系統(tǒng)按照預期的方式運行,都是服務架構(gòu)要考慮的問題。
下面我們簡單串一下主流的幾個服務架構(gòu),包括分層架構(gòu)、client-queue-worker架構(gòu)、微服務架構(gòu)、事件驅(qū)動架構(gòu)、大數(shù)據(jù)、大計算架構(gòu),并從四個方面對每個架構(gòu)進行總結(jié):
- 架構(gòu)的描述和架構(gòu)圖
- 推薦的使用場景
- 優(yōu)點、潛在問題和最佳實踐
- 一些現(xiàn)實場景中的示例
分層架構(gòu)
WAF全稱Web Application Firewall,就是防火墻
在開發(fā)傳統(tǒng)企業(yè)應用中,分層架構(gòu)得到了廣泛使用。一個應用被劃分為多個邏輯功能的層,比如展示層、業(yè)務邏輯層和數(shù)據(jù)訪問層。這些分層同時也定義了依賴關系,每個層都只能調(diào)用它下面的層。每個層可以是一個獨立的模塊,整個系統(tǒng)的各個模塊可以獨立甚至并行開發(fā)和測試,交付質(zhì)量可以得到比較好地保證,所以這是目前最為廣泛使用的架構(gòu)之一。但它也有一些難以解決的問題,尤其體現(xiàn)在產(chǎn)品上線后的變更上。體現(xiàn)在:
- 在大型系統(tǒng)中,層的劃分邏輯并不那么明顯,可能出現(xiàn)過度分層的問題
- 分層往往是從技術角度做的,沒有按照業(yè)務領域進行,導致系統(tǒng)對業(yè)務擴展不友好
- 分層以后,跨層通信比較困難,對性能敏感的業(yè)務無法接受由此帶來的網(wǎng)絡通信開銷和編解碼開銷
- 迭代困難,因為需要所有層的變更,協(xié)調(diào)多個團隊的成本非常高
分層架構(gòu)在私有云系統(tǒng)中非常常見,比如一個私有云的解決方案可以設計為:
- 物理機層:物理機、網(wǎng)絡設備等
- 虛擬化層:將物理資源進行虛擬化,可以用kvm
- 資源管理層:對資源進行調(diào)度編排,也提供故障恢復、彈性擴容等功能,比如k8s
- 服務編排層:定義和管理服務的部署、配置和自動化,通常是k8s上做二次開發(fā)出的一層殼
- 用戶展示層:通常是web界面、命令行,也可以是API
任務調(diào)度架構(gòu) Web-Queue-Worker
這個架構(gòu)下,用戶通過前端Web頁面將任務異步發(fā)送到后端,協(xié)議可以是HTTP或RPC。通常情況下,后端的worker接收任務后,執(zhí)行一段事件CPU密集型計算,生成結(jié)果。
作為對比,分層架構(gòu)中來自client的請求大都同步到達,請求可以很快得到滿足,server端處理完成后同步返回;相反,任務調(diào)度架構(gòu)下,每個請求要得到滿足,可能耗費server大量的計算/網(wǎng)絡或存儲資源,所以異步返回。
在通信方式上,任務調(diào)度架構(gòu)更多地采用類似于隊列的方式(不一定真的有一個消息隊列,從數(shù)據(jù)庫拉取任務也算)
微服務架構(gòu)
如果應用非常復雜,可以采用微服務模式。微服務應用是由很多小且獨立的服務組合而成,每個服務都獨立實現(xiàn)一套完整的業(yè)務能力。服務的關系非常松散,僅通過API進行通信。
每個服務都可以由一個獨立的研發(fā)團隊進行開發(fā),理論上也可以單獨部署,不用和其他團隊進行太多的協(xié)同。因此,微服務架構(gòu)非常鼓勵頻繁的更新。一個微服務架構(gòu)可以非常復雜,它可以由多個分層架構(gòu)應用和任務調(diào)度架構(gòu)應用組合而成。
由于服務非常多,DevOps的重要性就凸顯出來了。如果操作正確的話,這種架構(gòu)可支持高度靈活的發(fā)布節(jié)奏、更快的創(chuàng)新和高度的彈性及擴展性。
目前大型互聯(lián)網(wǎng)公司普遍采用微服務架構(gòu),處理用戶側(cè)發(fā)起的short-lived請求,以支撐超高的QPS。
事件驅(qū)動架構(gòu)
事件驅(qū)動架構(gòu)采用了訂閱-發(fā)布模型,也叫生產(chǎn)者-消費者模型。生產(chǎn)者負責發(fā)布事件到消息隊列,消費者訂閱消息隊列。生產(chǎn)者和消費者互相獨立,多個消費者之間也互相獨立。
依賴的中間件有 Kafka、RocketMQ、Redis Pub/Sub 等。
事件驅(qū)動架構(gòu)下,應用程序可以以非常低的延遲處理大量的數(shù)據(jù),在數(shù)據(jù)采集分析場景下使用非常廣泛。比如IoT場景、大型互聯(lián)網(wǎng)應用的數(shù)據(jù)收集子系統(tǒng)(日志/埋點數(shù)據(jù)回收)。
大數(shù)據(jù)、大計算
大數(shù)據(jù)是目前互聯(lián)網(wǎng)的標配場景,它的第一步一般是流式地搜集應用日志,清洗后存到分布式存儲中,應用到離線場景,或分發(fā)到消息隊列,用于流式處理。這一點與事件驅(qū)動架構(gòu)有部分重疊。
當我們聊大數(shù)據(jù)是,通常是說對一個超大數(shù)據(jù)集進行分片/區(qū),執(zhí)行并行計算,最終產(chǎn)出分析和報表。數(shù)據(jù)集大小可能是PB級。
大計算,也叫高性能計算(HPC),可以在上千核的CPU上并行計算。除了我們熟悉的大數(shù)據(jù)場景,也應用在圖形渲染、流體動力學、金融風險建模、石油勘探、藥物設計等領域。
不同架構(gòu)模式的局限
任何架構(gòu)在設計上都有受到一些限制,比如架構(gòu)基本元素的形態(tài),以及元素之間允許存在的關系。這些限制本質(zhì)上是在某種架構(gòu)下,我們可選的最大集合,它影響甚至間接塑造了架構(gòu)的最終形態(tài)。當應用的構(gòu)建遵循某種架構(gòu)模式時,一些好的符合預期的特性也會出現(xiàn)。
上面這段話有點抽象,我們以微服務架構(gòu)的限制為例:
- 每個服務承擔獨立單一的職責
- 服務之間相互獨立
- 數(shù)據(jù)只歸屬于擁有它的服務,服務之間不共享數(shù)據(jù)的所有權(quán)
遵循這些限制之后,系統(tǒng)中的服務就可以獨立進行部署。收益時事故隔離、支持頻繁更新、可便捷地引入新技術。
在選擇某種架構(gòu)模式之前,我們需要理解架構(gòu)的底層原則和限制。否則,架構(gòu)設計只在最表層符合某種架構(gòu)模式,但無法發(fā)揮這種架構(gòu)模式的潛力。在使用架構(gòu)過程中,務實很重要,有時候我們可能要放寬一些限制,而不是堅持架構(gòu)的純粹。
下面這張表總結(jié)了不同的架構(gòu)模式如何管理依賴,以及適用的業(yè)務領域
架構(gòu)模式 | 依賴管理 | 適用業(yè)務場景 |
分層架構(gòu) | 按照子網(wǎng)進行水平分層 | 傳統(tǒng)業(yè)務領域,更新頻率不高 |
Web-queue-worker | 前后端任務分離,通過異步消息進行解耦 | 相對簡單的業(yè)務場景,需要執(zhí)行一些資源密集型任務 |
微服務架構(gòu) | 功能/垂直節(jié)藕的服務,通過API調(diào)用進行通信 | 比較復雜的業(yè)務場景,支持高頻率的更新 |
事件驅(qū)動架構(gòu) | 生產(chǎn)者/消費者,每個子系統(tǒng)有獨立的數(shù)據(jù)視圖 | IoT和實時系統(tǒng) |
大數(shù)據(jù)架構(gòu) | 將一個超大數(shù)據(jù)集拆分成小的數(shù)據(jù)塊,在之上進行并行計算 | 批處理和流式處理的數(shù)據(jù)分析,機器學習模型支持的預測分析 |
大計算架構(gòu)(高性能計算) | 數(shù)據(jù)被分配到上千核CPU上進行計算 | 計算密集型的場景,比如模擬系統(tǒng) |
不同架構(gòu)模式面臨的挑戰(zhàn)vs收益
架構(gòu)的限制使其在某些場景下面臨一些挑戰(zhàn),所以在采用這些架構(gòu)模式時,需要理解其中的利弊權(quán)衡。我們需要保證,在我們所在的子領域(場景),疊加場景的限制條件下,架構(gòu)帶來的收益超過要面臨的挑戰(zhàn)。
下面列出了在選擇架構(gòu)模式時面臨的四類挑戰(zhàn):
- 復雜性。架構(gòu)的復雜性是否匹配我們所在的業(yè)務領域?換句話說,架構(gòu)模式在處理這個業(yè)務領域時是否太簡單,以至于無法處理將來的情況?如果是,那么未來系統(tǒng)會演變成一堆屎山,因為架構(gòu)無法幫你梳理清楚依賴關系。
- 異步消息和最終一致性。異步消息可以幫助我們解耦服務,增加系統(tǒng)穩(wěn)定性和擴展性。但是在最終一致性上可能會有問題,比如重復消息、亂序消息。
- 服務間通信。把應用拆分成多個獨立的服務之后,服務間的通信延遲可能成為一個風險,在數(shù)據(jù)量快速增長的情況下尤為明顯。比如在微服務架構(gòu)下面臨的問題可能有,接口延遲過高,或者網(wǎng)絡擁塞。
- 可管理性。管理應用的難度如何,包括監(jiān)控、部署、更新等等?