對,各位你沒看錯,我的部落格在隔了一年半之後又有新文章了 XD
好久沒寫了,這年頭什麼東西都流行加個 "微" ... BLOG 有微博,Messenger 有微信... MV有微電影... 連我們在做的數位學習也出現 "微型課件" ... 什麼都微型化的後果,就是越來越懶的 POST 這種 "大型" 的文章在 BLOG 上了.. 常常想到一些東西,還沒成熟到一個完整概念,就貼到 FB 上,越來越速食的結果就越來越沒顧到 BLOG... Orz…
不過,世界果然是在往M型的方向發展,雲端到現在已經是個成熟的技術 & 概念了,WEB APP的開發也越來越大型化,用了 Azure 當 PaaS (Platform as a Service) 後,要開發大型的 Web Application 門檻也不像過去那麼高。這次要寫的,就是 SaaS (Software as a Service) 被廣為流傳的設計概念: 多租戶 (Multi-Tenancy) 的設計方式。
其實說明 SaaS 或是 Multi-Tenancy 的文章一大堆,完全輪不到我這種文筆程度的人來寫 XD,一樣,我只針對特別的地方下筆。Multi-Tenancy 顧名思義,就是讓一個 Application 能做適當的切割,"分租" 給多個客戶使用。跟過去一個 Application 就服務一個客戶不一樣,Multi-Tenancy 先天就是設計來服務多個客戶用的,也因為當年 SalesForce 的成功而聲名大噪。
回到系統的角度來思考,要設計一個漂亮的 Multi-Tenancy (Web) Application, 還真的是個不小的挑戰... 沒錯,我就吃過這種苦頭 XD,大概六年前因為工作上的關係,就已經有這樣的設計架構了,不過當年一切都要自己來,因此什麼釘子都碰過了。用現在的技術,有太多簡潔的作法,不過確看不到有太多的人在討論 (至少中文的沒有),就動起這念頭,想來寫幾篇.. 內容就定位在用當紅技術: Microsoft Azure + ASP.NET MVC4 當作底層開始吧~~
先來探討一下幾種常見的 Multi-Tenancy 的設計方式。MSDN 有篇文章寫的很精闢,快七年前的文章了,當年靠著這篇給我不少靈感... 我就先來導讀一下,標一下幾個架構設計的重點 (底下圖片皆引用 MSDN 該篇文章):
三種架構: Separated DB / Separate Schema / Shared Schema 比較:
要把多個客戶塞進同一套系統內,最直接的問題就是資料隔離的 issue 了。暫時不管 application, 只管 data, 若對隔離及安全性要求越高,就要在越底層就做到隔離的機制。
- Separated DB
最高隔離等級,就是每個客戶一個 database (Separated DB)。用這種模式,再怎麼粗心的工程師,也不會不小心把別的客戶的資料給秀出來。舉個例,系統內的A客戶,就會連到A資料庫,B客戶就用B資料庫。每個客戶的資料庫各自獨立,不會互相打架。
- Separate Schemas (Shared Database)
這種作法比第一種 Separated DB 好一點,它共用同一個 DB,但是替每一個客戶建立一組 Tables。這種作法不需要那麼高的成本 (看過 $$ 就知道,資料庫很貴的….),多個客戶可以共用資料庫,不過因為 Schema 的層級隔離了,簡單的說不同客戶的 Table Name 是不一樣的,因此粗心的工程師造成客戶資料混在一起的機率也不算高,還有不錯的隔離機制。
這方式實作有點辛苦,不過 SQL 2005 之後開始支援 Schema 這機制,實作上可以簡單的多。
- Shared Schema (Shared Database & Shared Schema)
這作法最極端了,所有資料都放在同一個資料庫,同一組資料表... 靠的是一個客戶ID的欄位來區別。這種方式成本最低,設計也最簡易直覺,不過... 整個系統只要有一道 SQL query 寫錯 (漏掉 where TenantID = ‘MyAccount’),一切就完了,A客戶的資料就會出現在B客戶的報表裡...
當然,這篇是 MSDN 的文章,自然也提到了 Microsoft 的技術 (SQL server) 如何因應這三種不同的需求。這張表格是整篇文章的精華了,很清楚的講到三種模式,對各種問題的最佳處理方式。表格貼不過來 @@,我直接用截圖來說明:
簡單舉個例子,Extensibility Patterns 這欄說明的是如何擴充你的資料? 這裡指的擴充不是指效能,是只你要如何增加新的資料型態?
Separate DB or Shared DB 最簡單,就照一般的方法,開新的欄位就好。對於 Shared Schema 的系統來說就沒這麼容易了,只能預先開幾個備用欄位 (如每個 table 都開: column1, column2, column3 …. etc),不然就只能弄出像 NO SQL 那種 Name-Values 的方式來處理。不過,有經驗的開發者都知道,這樣搞下去,QUERY 實在很難寫...
其實這篇文章講的很務實,從設計架構、開發、到系統上線的維護及調校都講的很清楚,若各位有在企業內部 (INTRANET) 的環境建立 Multi-Tenancy Application 的需求,只能用 Windows Server + SQL Server 的話,這篇文章很值得參考。不過,這篇文章的時空被景是 2006 年,當年沒有 Azure 這種東西... MVC 也沒今天那麼成熟... 現在要做同樣的事,你有更厲害的武器可以用...
現在該怎麼做? 當然是等下一篇 XD