表1 多租戶業(yè)務(wù)表結(jié)構(gòu)
通過TenantID字段來獲得對應(yīng)租戶的業(yè)務(wù)數(shù)據(jù)。當(dāng)系統(tǒng)用到租戶的業(yè)務(wù)數(shù)據(jù)時(shí),需要在每條SQL語句中增加‘TenantID = ?’ 條件進(jìn)行業(yè)務(wù)數(shù)據(jù)操作。
(2) 數(shù)據(jù)擴(kuò)展技術(shù)
為了滿足不同租戶的不同需求,SaaS軟件必須能夠保證對數(shù)據(jù)可擴(kuò)展。多租戶模式滿足大規(guī)模租戶對數(shù)據(jù)的個(gè)性化需要,最常見的解決方案就是實(shí)現(xiàn)擴(kuò)展數(shù)據(jù)的可配置。實(shí)現(xiàn)數(shù)據(jù)的可配置有以下3種常見方案。
方案1:定制字段,就是根據(jù)租戶的需要在各租戶共有的數(shù)據(jù)表上添加相應(yīng)的定制字段來保存擴(kuò)展數(shù)據(jù)。這種方案數(shù)據(jù)擴(kuò)展非常簡單但是其擴(kuò)展性非常有限,當(dāng)租戶量達(dá)到一定數(shù)量,表中添加的字段就會非常多,而且每個(gè)租戶添加的字段對另外租戶是沒有任何意義的,嚴(yán)重破壞了表的結(jié)構(gòu),有些擴(kuò)展字段可能為空,浪費(fèi)了表空間。
方案2:預(yù)分配字段,該方法在表格中提供一定數(shù)量的預(yù)設(shè)字段,當(dāng)租戶要擴(kuò)展數(shù)據(jù)時(shí),從表中選取適當(dāng)?shù)念A(yù)設(shè)字段進(jìn)行擴(kuò)展,但是不同租戶選取同一個(gè)預(yù)設(shè)字段的含義可能也不一樣。如表2中TenantID字段區(qū)分每個(gè)租戶,除了一些固定的字段外,還提供了一些預(yù)分配字段,Ext1、Ext2、Ext3就是預(yù)分配的字段,預(yù)分配字段的使用由租戶自己預(yù)定,一般初始為字符串類型,其真實(shí)類型可以采用元數(shù)據(jù)表來進(jìn)行跟蹤。
表2 預(yù)分配字段方案表結(jié)構(gòu)
這種方案雖然能滿足可配置、可擴(kuò)展的需求,但是預(yù)留過多浪費(fèi)空間,預(yù)設(shè)過少,又不能滿足租戶的需求。
方案3:名稱值對,本方案采用一個(gè)單獨(dú)的表來存儲擴(kuò)展數(shù)據(jù)。擴(kuò)展表將數(shù)據(jù)表的橫向擴(kuò)展列轉(zhuǎn)換成縱向的擴(kuò)展數(shù)據(jù)集,為每一條原數(shù)據(jù)記錄設(shè)一個(gè)擴(kuò)展字段,保存為擴(kuò)展表中的一條記錄。將數(shù)據(jù)表中的數(shù)據(jù)記錄與元數(shù)據(jù)表中的配置記錄相關(guān)聯(lián),構(gòu)成擴(kuò)展數(shù)據(jù)記錄。如圖1所示。
圖1 名稱值對擴(kuò)展表結(jié)構(gòu)
雖然這種方案很好地達(dá)到了多租戶數(shù)據(jù)擴(kuò)展的靈活性要求,但增加了查詢、更新記錄等數(shù)據(jù)庫操作的復(fù)雜度,每次操作都涉及到多個(gè)表間的關(guān)聯(lián),因此該方案也有待優(yōu)化。
方案4:XML共享模型的數(shù)據(jù)擴(kuò)展,這種方案在數(shù)據(jù)表中采用一種XML數(shù)據(jù)類型字段來存儲租戶間的數(shù)據(jù)。當(dāng)今主流的關(guān)系數(shù)據(jù)系統(tǒng)都支持XML數(shù)據(jù)的存儲和管理,并提供了很多函數(shù)來直接對XML文檔節(jié)點(diǎn)進(jìn)行管理。下面以O(shè)racle數(shù)據(jù)庫系統(tǒng)為例。
表結(jié)構(gòu):TableName(TenantID,Col1,Col2,,XMLDataField),其中TenantID、Col1、Col2字段是所有租戶共用的字段;XMLDataField字段存儲租戶特有的異構(gòu)數(shù)據(jù),其格式完全遵循XML的格式。設(shè)計(jì)XMLDataField字段的格式如下:
value1
value2
value3
……
XML文檔中每個(gè)子節(jié)點(diǎn)代表租戶的一個(gè)擴(kuò)展列,包括列名、列的數(shù)據(jù)類型、列所對應(yīng)的值等信息。每增加一個(gè)擴(kuò)展列就在相應(yīng)的XML文檔中添加一個(gè)子節(jié)點(diǎn),滿足租戶對數(shù)據(jù)擴(kuò)展的個(gè)性化需要。
使用XML字段作為數(shù)據(jù)擴(kuò)展方案,對擴(kuò)展數(shù)據(jù)的操作簡單,不需頻繁地多表連接,可以靈活地滿足多租戶模式下的異構(gòu)數(shù)據(jù)的定制,提高了性能。該方案的使用需要在系統(tǒng)的架構(gòu)模式中添加一層對XML數(shù)據(jù)進(jìn)行解析再呈現(xiàn)給客戶以及對客戶數(shù)據(jù)封裝成XML數(shù)據(jù)再保存到數(shù)據(jù)庫中。
2.3 多租戶模式下的功能可配置
SaaS軟件所強(qiáng)調(diào)的是“按需使用,按需付費(fèi)”。在SaaS模式下,租戶根據(jù)自己不同的需求來使用同一軟件,則需達(dá)到可配置性要求。實(shí)現(xiàn)功能的可配置,可采用如圖2所示的四級表結(jié)構(gòu)。
圖2 四級表結(jié)構(gòu)
每個(gè)租戶對應(yīng)一個(gè)預(yù)設(shè)的功能模式,預(yù)設(shè)了租戶的基本功能。功能模式由多個(gè)原子功能構(gòu)成。租戶表存儲租戶的相關(guān)信息,TenantID:租戶的唯一標(biāo)識;UserName:租戶的登錄賬號;Password:租戶的登錄密碼;PatternNo:租戶使用系統(tǒng)包括的功能模式。功能表存儲了系統(tǒng)所有的原子功能相關(guān)信息,MENU_No:原子功能唯一標(biāo)識;MENU_NAME:原子功能的名稱。模式表存儲了功能模式信息。PatternNo:系統(tǒng)中包括的所有模式標(biāo)識。MENU_No:功能模式包括的原子功能。模式表可以作為租戶選擇功能的向?qū)?。租戶模式功能表存儲了租戶所擁有的功能的相關(guān)信息。租戶模式功能表定義了該租戶所有的功能信息,該表可以作為租戶所擁有的所有功能的查詢。
3 SaaS模式下的體系架構(gòu)設(shè)計(jì)
軟件系統(tǒng)架構(gòu)決定了系統(tǒng)的靈魂,好的體系架構(gòu)可以保證系統(tǒng)的穩(wěn)定性、健壯性、可擴(kuò)展性、兼容性和可用性,而傳統(tǒng)軟件通常需要采用分層的設(shè)計(jì)思想,一般大致分為5層,包括客戶層、表現(xiàn)層、控制層、業(yè)務(wù)邏輯層、數(shù)據(jù)庫層。這種傳統(tǒng)軟件的體系架構(gòu)分層不能很好地滿足SaaS軟件的可擴(kuò)展性和可配置性,難以滿足SaaS模式下多租戶的個(gè)性化需要。因此在討論了SaaS軟件關(guān)鍵技術(shù)之后,本文提出SaaS模式下的體系架構(gòu)。在傳統(tǒng)軟件體系架構(gòu)的基礎(chǔ)上增加配置管理層和數(shù)據(jù)模式選擇層。根據(jù)多租戶的不同需要配置管理層可以對系統(tǒng)的功能進(jìn)行配置管理,選擇滿足自身業(yè)務(wù)需要的功能。數(shù)據(jù)模式選擇層是軟件供應(yīng)商為了考慮各種租戶對系統(tǒng)的不同需求而對數(shù)據(jù)存儲模式進(jìn)行選擇。如果數(shù)據(jù)擴(kuò)展方案采用的是XML數(shù)據(jù)字段,則需要在此基礎(chǔ)上添加一層XML數(shù)據(jù)處理層,完成對XML數(shù)據(jù)的解析、封裝處理。這樣的體系架構(gòu)可以極大地滿足大規(guī)模的各種行業(yè)的租戶,具有極大的可擴(kuò)展性。SaaS系統(tǒng)體系架構(gòu)如圖3所示。
圖3 SaaS體系架構(gòu)
本文就傳統(tǒng)軟件向SaaS軟件轉(zhuǎn)型的一些關(guān)鍵技術(shù)進(jìn)行了研究,并給出了一些技術(shù)可行的解決方案。在此基礎(chǔ)上對傳統(tǒng)軟件體系架構(gòu)進(jìn)行修改,總結(jié)出了SaaS軟件的體系架構(gòu)模型,可以很好地滿足SaaS軟件的可擴(kuò)展性和可配置性要求。本文對SaaS軟件的安全性研究涉及較少,安全性[5]是決定租戶對SaaS軟件信任的關(guān)鍵要素,只有很好的安全保障才能讓租戶放心地使用SaaS軟件。因此,后期將會對安全性問題進(jìn)行詳細(xì)的研究。