我們在做系統(tǒng)架構(gòu)設(shè)計的時候,經(jīng)常離不開的一個話題就是進(jìn)行服務(wù)的隔離設(shè)計。
那什么是「服務(wù)隔離」呢?
顧名思義,它是指將系統(tǒng)按照一定的原則劃分為若干個服務(wù)模塊,各個模塊之間相對獨立,無強(qiáng)依賴。當(dāng)有故障發(fā)生時,能將問題和影響隔離在某個模塊內(nèi)部,而不擴(kuò)散風(fēng)險,不波及其它模塊,不影響整體的系統(tǒng)服務(wù)。
其實隔離設(shè)計并非軟件行業(yè)獨創(chuàng),它是借鑒于造船行業(yè)。
如上圖,造船行業(yè)有一個專業(yè)術(shù)語叫做「艙壁隔離」。利用艙壁將不同的船艙隔離起來,如果某一個船艙進(jìn)了水,那么就可以立即封閉艙門,形成艙壁隔離,只損失那一個船艙,其他船艙不受影響,整個船只還是可以正常航行。
一、為什么要做服務(wù)隔離設(shè)計呢?
我們在做系統(tǒng)設(shè)計的時候,必須有一個清楚的認(rèn)知是:任何軟件系統(tǒng),故障是不可避免的,并且大多數(shù)還是不可預(yù)測的,因此,我們只能在系統(tǒng)的設(shè)計之初就充分的考慮好應(yīng)對措施,如何在故障發(fā)生時,去盡最大可能的止損和減少故障范圍。
沒有人敢說他的系統(tǒng)是百分百可用,我們能做的就是,使用一切方法去減少故障的影響面,盡可能的去提高系統(tǒng)的整體可用率。
而把系統(tǒng)分離成子服務(wù),將子服務(wù)進(jìn)行一定程度隔離的做法,能保證在有不可預(yù)測的故障發(fā)生時,縮小故障范圍的最佳手段。
二、服務(wù)隔離應(yīng)該怎么做?
那在實際項目中,一般通過什么方法去做服務(wù)隔離呢?主要有以下兩種:
按服務(wù)/功能做隔離
按用戶分類隔離
首先說一下按照服務(wù)進(jìn)行隔離的做法。
網(wǎng)上找了一張圖,雖然原圖的作用不是用來表述這個的,但是也類似,將就看吧。
比如上圖里面,微博項目可以把 Feed信息流、用戶系統(tǒng)、評論系統(tǒng) 都分拆為獨立業(yè)務(wù)模塊,這些模塊無論是對外的接口應(yīng)用、還是到數(shù)據(jù)庫、到底層硬件資源都是完全隔離的。其中任何一個模塊的故障,理論上都不會影響到其它模塊。
再舉個例子,如果我們要設(shè)計個電商平臺,可以將其中的 用戶系統(tǒng)、訂單系統(tǒng)、支付系統(tǒng)、倉儲系統(tǒng) 都分別進(jìn)行獨立隔離,這樣做就是從服務(wù)層面實現(xiàn)了故障的隔離效果。
那按照服務(wù)隔離有沒有弊端呢?有,肯定有。
當(dāng)我們某個功能操作需要關(guān)聯(lián)多個服務(wù)模塊或者同時查詢所個模塊數(shù)據(jù)的時候,代碼寫起來就會相對麻煩一些了,其中涉及到多模塊調(diào)用的性能問題、數(shù)據(jù)一致性問題、事物問題等。
不同服務(wù)模塊之間的交互也會比較復(fù)雜一些,因為要做服務(wù)隔離,避免服務(wù)強(qiáng)依賴,所以模塊之間的交互調(diào)用最好是走異步模式,需要通過異步線程或消息中間件來傳遞實現(xiàn)。
在進(jìn)行運營大數(shù)據(jù)分析的時候,由于數(shù)據(jù)是散落在不同服務(wù)模塊的,因此需要做額外的匯聚操作,還得有唯一字段保證數(shù)據(jù)在不同模塊產(chǎn)生的先后順序。
接下來說一下按用戶隔離的做法。
繼續(xù)網(wǎng)上找圖,雖然原圖的作用不是用來表述這個的,但是也類似。粉絲又不多,我又懶得畫圖,將就看吧,多發(fā)揮一下想象力,哈哈。
簡單一句話解釋就是:我們先部署多套一模一樣的業(yè)務(wù)服務(wù),然后將用戶根據(jù)一定的特征去做分類,讓不同分類的用戶去訪問不同的業(yè)務(wù)實例,達(dá)到分流和隔離的效果。
怎么給用戶分類?
可以用按照用戶是否VIP、用戶等級、用戶IP等等,方法很多,要結(jié)合自己實際業(yè)務(wù)的特性來做。
其實這也是一種「多租戶架構(gòu)」,在SaaS服務(wù)中用得比較多。
多租戶模式有三種形式:
完全的隔離,即服務(wù)和數(shù)據(jù)都是完全獨立的。
公共服務(wù)、獨立數(shù)據(jù)源,即多個租戶是用的同一臺服務(wù)程序,但是底層的數(shù)據(jù)源是獨立的。
公用服務(wù)、公用數(shù)據(jù)源,即多個租戶的服務(wù)程序與數(shù)據(jù)庫源都是共享的,不同數(shù)據(jù)可能會做分區(qū)分表來獨立。
上述三種方式,從下到上,獨立性和安全性越來越高,資源利用率越來越低,根據(jù)業(yè)務(wù)特性去選擇,一般選擇折中方案。
另外,功能隔離和用戶隔離 兩種方式并非互斥的,是可以結(jié)合在一起使用的。
三、服務(wù)隔離的注意事項
我們在做服務(wù)隔離的時候,還是有一些原則和事項需要注意的:
不可越界:能在隔離模塊內(nèi)完成的邏輯,就盡量不要跨模塊調(diào)用,減少依賴。
不可共享:數(shù)據(jù)和資源能獨享的就盡量不要共享,不然很容易造成隔離失效。
考慮效率:設(shè)計隔離模塊的時候,要根據(jù)業(yè)務(wù)情況而定,充分的考慮到未來的拓補(bǔ)結(jié)構(gòu),減少調(diào)用效率的損失。
考慮顆粒度:隔離模塊設(shè)計的大小問題,過大和過小都不合適,需充分考慮。
服務(wù)的全面監(jiān)控:既然服務(wù)或用戶進(jìn)行隔離了,那么系統(tǒng)的復(fù)雜度肯定是比之前要高了,那么針對多服務(wù)的全鏈路監(jiān)控是必不可少的。
服務(wù)隔離的設(shè)計模式能降低依賴服務(wù)對整個系統(tǒng)的影響,保護(hù)有限的資源不被耗盡,提高了整個系統(tǒng)的可用性。本文參考了很多其它資料,屬于拋磚引玉,希望大家能一起交流,提出更好的架構(gòu)設(shè)計思路。