Saas多租戶系統(tǒng)的架構(gòu)設(shè)計

Saas系統(tǒng)分級

SaaS系統(tǒng)架構(gòu)成熟度模型的5個級別——從“混亂”到“烏托邦”。

第0級(混亂):每次新增一個客戶,都會新增軟件的一個實例。
第1級(受控的混亂):所有客戶都運行在軟件的同一個版本上,而且任何的定制化都通過修改配置來實現(xiàn)。
第2級(多租戶[multi-tenant]、高層建筑[Highrise]):所有的客戶都已經(jīng)可以在軟件的同一個版本上運行了,而且他們都在同一個“實例”上運行。
第3級(多租戶, 擴建[Build-Out]):此時你已經(jīng)擁有了多租戶、單一版本的軟件模型。不過你還是可以通過硬件擴展(scale-out)的方式來進行擴充。
第4級(烏托邦):如同第3級,除非你可以找出有效的方式,以在不同的“實例”上運行不同版本的軟件。

應(yīng)用程序必須支持多租戶:

多租戶可以分為幾個不同的類別(如列表下方的圖所示):   
1.1,云中的簡單虛擬化,其中只對硬件進行共享。   
1.2,共享應(yīng)用程序,對每個租戶使用不同的數(shù)據(jù)庫。   
1.3,共享應(yīng)用程序和數(shù)據(jù)庫(效率最高,真正的多租戶)。

1. 分層設(shè)計

Saas 系統(tǒng)分層大概是:

image.png

Saas系統(tǒng)分層:租戶識別 > 應(yīng)用層 > 數(shù)據(jù)訪問層 > 緩存層 > 數(shù)據(jù)庫

業(yè)務(wù)代碼都是寫在應(yīng)用層。
租戶識別可以用spring攔截器實現(xiàn),然后使用ThreadLocal傳遞給后端
數(shù)據(jù)庫和緩存層對應(yīng)用層應(yīng)該是透明的。程序員在寫代碼的時候,只關(guān)心業(yè)務(wù)邏輯,不應(yīng)該擔心多租戶的問題。

2. 數(shù)據(jù)隔離要透明

saas系統(tǒng)說起來很簡單,任何系統(tǒng)似乎加個tenant_id(租戶id)就變成saas系統(tǒng)了。比如原來的用戶登錄是:

image.png

改成

image.png

對于復雜業(yè)務(wù)的saas系統(tǒng),這樣做法非常危險,而且開發(fā)效率很低。你想想如果那個程序員寫sql時候忘了加 “ and tenant_id =1” ,結(jié)果不堪設(shè)想。

比較好做法是在數(shù)據(jù)庫訪問層對SQL進行改寫。

image.png

在連接池根據(jù)TenatnContext改寫Sql。

這樣做好處是,一來程序猿最多把系統(tǒng)搞down了,也不至于信息串了互相泄露。二來將來做分表分庫也很方便,上層應(yīng)用不用修改。

3. 租戶識別方案

比較好做法是通過url識別租戶。系統(tǒng)是給租戶生成一個隨機的三級域名,比如 abc.crm.baidu.com. 如果客戶想使用自己的域名,可以在cname到我們生成的三級域名,并在管理系統(tǒng)里面做綁定。

這樣一個租戶可以有兩個域名,訪問saas,一個隨機生成的三級域名,另外一個租戶自己的域名.代碼里面可以根據(jù)過來的域名,判斷是那個租戶然后初始化TenantContext.

如果不想通過域名來做,也可以通過登錄名來判斷。這種方式要涉及到租戶切換問題。

4. 智能DNS

Nginx中rewrite實現(xiàn)二級域名、三級域名、泛域名、路徑的重寫

5. 租戶管理系統(tǒng)(計費,訂購,定制,充值,催繳)

Saas系統(tǒng)是必須考慮計費系統(tǒng)和租戶控制系統(tǒng)。這個系統(tǒng)需要都是獨立設(shè)計。比如那個租戶購買了那些模塊,一個月多少錢。租戶可以創(chuàng)建最多的用戶數(shù)。計費到期郵件提醒等功能。

計費方式一般有兩種,周期性計費,類似月租方案,和使用量計費,用多少付多少。周期性計費比較簡單。也可以兩者結(jié)合起來。

6. 定制化開發(fā)

SAAS的優(yōu)勢在于一套系統(tǒng)多人使用,似乎和定制化開發(fā)有沖突。比如A客戶想要A功能,B客戶不想要。但定制化開發(fā)是無法避免的,比如CRM系統(tǒng)這樣復雜的系統(tǒng),不可能一套系統(tǒng)滿足所有公司的要求。定制化開發(fā)盡可能分系統(tǒng),分模塊去做。然后通過控制臺中配置不同租戶訂購不同模塊,那些模塊可以在前端頁面上顯示。不同的子系統(tǒng)需要分開部署。前端可通過nginx根據(jù)url分發(fā),比如 abc.crm.baidu.com/bi/xxx/xx這個地址,就分發(fā)到BI子系統(tǒng)。不要嘗試OSGI去搞模塊化,這個是個大坑。

還有開發(fā)和產(chǎn)品,現(xiàn)有需求一定要分析清楚,不要一上線發(fā)現(xiàn)后患無窮。新功能盡量做的獨立可以配置。

7. 灰度升級

SAAS付費企業(yè)客戶對系統(tǒng)問題都特別敏感。為了減少升級可能出現(xiàn)問題的影響范圍,一般都采用灰度升級策略。如果使用了url來區(qū)分不同租戶,灰度升級配置就會很方便。可以配置nginx 來根據(jù)域名做分發(fā),比如租戶A(aaa.com)到實例1(版本1.0),租戶B(bbb.com)到實例2(版本). 當需要域名配置非常多的時候,nginx配置文檔會亂。這塊時候可以考慮使用nignx_lua來寫一些擴展模塊。

8. 容量估計

對高并發(fā)的估計,讀寫操作的頻率估計。

9. Saas平臺架構(gòu)分層分析

Saas平臺架構(gòu)需要完成從用戶申請鏈接saas到用戶對自己購買的功能模塊的應(yīng)用整個過程,用戶用起saas看似簡單快捷,但這個過程卻需要saas平臺架構(gòu)默默完成的非常復雜的處理過程。通過對saas平臺架構(gòu)的了解,可以清晰的分化數(shù)據(jù)的處理過程,讓用戶也可以明白saas平臺架構(gòu)處理數(shù)據(jù)的優(yōu)勢。下面介紹:saas平臺架構(gòu)分為哪幾部分。

saas平臺架構(gòu)之呈現(xiàn)層:

saas平臺架構(gòu)的呈現(xiàn)層可以使用的客戶端可能都瀏覽器或本地客戶端。如果是瀏覽器則需要Web界面技術(shù)、交互技術(shù)等技術(shù)(如:HTMl5技術(shù)、CSS3技術(shù)、Ajax技術(shù)等)的支持,如果是軟件客戶端則需要遠程桌面技術(shù)、軟件交互技術(shù)等技術(shù)支持。

saas平臺架構(gòu)之調(diào)度層:

saas平臺架構(gòu)的調(diào)度層體現(xiàn)分布式系統(tǒng)的特性之一。調(diào)度層首先負責識別并通過AAA認證每個用戶請求,然后根據(jù)業(yè)務(wù)處理器的負載、業(yè)務(wù)特征進行合理的調(diào)度。通過應(yīng)用這樣的架構(gòu)SaaS平臺可以橫向擴展。此外在存儲、緩存等方面為了滿足平臺的橫向擴展需求,調(diào)度層也必須具有良好的可擴展性。

saas平臺架構(gòu)之業(yè)務(wù)層:

saas平臺架構(gòu)的業(yè)務(wù)層負責接收調(diào)度層轉(zhuǎn)發(fā)過來的請求,而且還要通過對接受到的請求執(zhí)行真正的業(yè)務(wù)邏輯。一般來說業(yè)務(wù)邏輯的執(zhí)行使用一臺服務(wù)器就夠了。因此業(yè)務(wù)層實際是由一排對等的服務(wù)器組成的,每臺服務(wù)器都執(zhí)行相同的業(yè)務(wù)邏輯。

saas平臺架構(gòu)之數(shù)據(jù)層:

saas平臺架構(gòu)的數(shù)據(jù)庫集群用于處理存儲關(guān)系性很強并且對事務(wù)性要求很高的業(yè)務(wù)數(shù)據(jù),這類數(shù)據(jù)目前還要用傳統(tǒng)的數(shù)據(jù)庫集群技術(shù)來解決,saas平臺架構(gòu)的數(shù)據(jù)庫集群主要是根據(jù)業(yè)務(wù)特征制定數(shù)據(jù)拆分方案。同時分布式數(shù)據(jù)庫用于存放海量但關(guān)系性不強的數(shù)據(jù)(如:用戶的操作日志等)。

以上是對“Saas系統(tǒng)架構(gòu)的思考,多租戶Saas架構(gòu)設(shè)計分析”的介紹,從saas平臺架構(gòu)處理數(shù)據(jù)可以看出saas平臺的應(yīng)用有很強的優(yōu)勢,如用戶使用saas非常方便簡單只要瀏覽器或本地客戶端接口,saas平臺處理數(shù)據(jù)要經(jīng)過層層認證saas產(chǎn)品安全可靠,saas平臺優(yōu)化處理數(shù)據(jù)提高saas性能。

多租戶Saas系統(tǒng)架構(gòu)還應(yīng)該滿足以下需求:

image.png

Saas 正在蓬勃發(fā)展,最近的銷售易被騰訊重金加持,看好 SaaS 系統(tǒng)的未來!

多租戶系統(tǒng)架構(gòu)

運行時架構(gòu)圖:

img_1

做為SaaS的基本特征,多租戶對系統(tǒng)的很多方面都產(chǎn)生了很多深遠的影響.就數(shù)據(jù)層面的架構(gòu)來說,基本上分成了多租戶共享單一數(shù)據(jù)庫、單一租戶獨享單一數(shù)據(jù)庫以及介于兩者之間的單一數(shù)庫下的單一租戶獨享單一schema三種方案。
這篇文章 http://msdn.microsoft.com/en-us/library/aa479086.aspx 對三種架構(gòu)方案做了全面和細致的分析,里面提到的pattern都是非常實用的(特別是Name-Value Pairs模式)。
讓我印象最深刻的是,本文在分析每種方案的利弊和適用場景時,視野寬廣,目光長遠,考慮到了很多過去我自己沒有想到過的因素。比如在談到數(shù)據(jù)安全時,作者舉例說對于某些類型的租戶對數(shù)據(jù)安全是非常關(guān)切的(比如銀行),這一類用戶是很難容忍將自己的數(shù)據(jù)與其他租戶放在一起的。再比如是否會考慮為租戶提供數(shù)據(jù)備份與恢復的增值服務(wù)供需要的租戶購買。還有就是綜合預期產(chǎn)品未來的租戶數(shù)量(10個和1000就會有質(zhì)的不同),平均每個租戶的數(shù)據(jù)量,以及單一租戶的并發(fā)訪問量等等.這些都會影響到方案的選擇.總之這是一篇關(guān)于多租戶Multi-Tenant數(shù)據(jù)架構(gòu)方面非常全面的文章!

nginx:主要做多域名映射,根據(jù)域名映射到不同的web Server,比如接受到域名A請求,則路由到web Server1,接受到域名B請求,則路由到web server2

web server:主要是放網(wǎng)頁或者web相關(guān)的,比如用戶登錄業(yè)務(wù)等,客戶多變的需求都放到這層實現(xiàn),比如有些客戶在要求自己的網(wǎng)站注冊的商家,必須上傳運業(yè)執(zhí)照,有些不需要等可變的需求

basic server:后臺服務(wù),這層的服務(wù)都是共有的,對于每個用戶都不變的基礎(chǔ)服務(wù)都放這層,并且這層做數(shù)據(jù)庫路由,每個域名一個數(shù)據(jù)庫(每個客戶一個數(shù)據(jù)庫,做數(shù)據(jù)隔離,當時個人還不同意,從事后來看,這種架構(gòu)確實好處比較多,特別是客戶以前就有一個網(wǎng)站,然后在往新庫里導數(shù)據(jù),然后又刪新庫里的數(shù)據(jù)時,不擔心會把其它客戶的數(shù)據(jù)刪掉)。

DB :每個客戶一個數(shù)據(jù)庫,做到數(shù)據(jù)上的邏輯隔離和物理隔離(當時設(shè)想每個外部客戶1個域名,然后在數(shù)據(jù)庫的每個表里加平臺id以區(qū)分是那個外部客戶的數(shù)據(jù),后來架構(gòu)師力排眾議,每個客戶1個數(shù)據(jù)庫,做到數(shù)據(jù)隔離,Basic Server做數(shù)據(jù)庫路由)

如何做數(shù)據(jù)庫路由?

web server根據(jù)請求的url,拿到域名,然后查出平臺id。
basic server中的每個接口,都需要帶平臺id字段。
web server 調(diào)用basic server接口時,傳入平臺id。然后在basic server的service層,做aop,根據(jù)參數(shù)里的平臺id,找到配置好的平臺id和數(shù)據(jù)庫連接信息,把連接信息放入ThreadLocal,包裝自己的DataSource,在DataSource里獲得數(shù)據(jù)庫連接時,用ThreadLocal里的數(shù)據(jù)庫連接信息,獲得數(shù)據(jù)庫連接,方法執(zhí)行完,清除數(shù)據(jù)庫連接(這里曾出現(xiàn)過小問題,service嵌套套用的時候,里面service方法退出清除數(shù)據(jù)庫連接,導致外面service在操作數(shù)據(jù)庫時,拿不到連接信息而報錯,后來增加了一個調(diào)用層次計數(shù))

日志監(jiān)控層

任何可以反映 SpringBoot 微服務(wù)運行狀態(tài)的數(shù)據(jù),對于監(jiān)控來說都是十分重要的“財產(chǎn)”,都應(yīng)該盡量采集上來進行分析,從而在分析的基礎(chǔ)上謀求對 SpringBoot 微服務(wù)的改進。

對于應(yīng)用日志來說,在單機單結(jié)點的年代,我們只要登錄應(yīng)用部署的服務(wù)器,然后使用 tail-f 之類的命令就可以實時地查看應(yīng)用日志信息,并決定如何做出應(yīng)對。

但對于 SpringBoot 微服務(wù)來說,數(shù)量上的特征已經(jīng)決定了單機單結(jié)點的方法已經(jīng)行不通了,如果還是一臺臺地去查看應(yīng)用日志,我們不但會“疲于奔命”,而且還無法及時有效地發(fā)現(xiàn)微服務(wù)作為一個邏輯服務(wù)集群整體上的狀態(tài)特征現(xiàn)在是什么樣的,我們這時候需要的是一種集中式的日志采集、存儲和分析平臺。

對于 Java 開發(fā)者來說,ELK 技術(shù)棧正是為此而生的(E=ElasticSearch,L=Logstash,K=Kibana),整個功能鏈路如圖 2 所示。

基本ELK技術(shù)棧功能鏈路示意圖

圖 2 基本ELK技術(shù)棧功能鏈路示意圖

不過,鑒于 ElasticSearch 對高頻度的寫入并沒有很高的承受力,在正式的生產(chǎn)環(huán)境中,我們一般會采用如圖 3 所示的部署結(jié)構(gòu)。

生產(chǎn)環(huán)境典型ELK技術(shù)棧功能鏈路部署示意圖

圖 3 生產(chǎn)環(huán)境典型 ELK 技術(shù)棧功能鏈路部署示意圖

即我們使用 Kafka 作為數(shù)據(jù)采集的緩沖區(qū),以便減輕從大量應(yīng)用結(jié)點采集日志并寫入 ElasticSearch 的負擔。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容