2012年4月6日 星期五

軟體專案的素質之四 ─ 整體設計之 架構設計案例

之前的架構設計篇,給出了takeshi在設計系統架構時,一般會依循的原則;在此篇文章takeshi嘗試提出一個實際的案例,來回應之前的文章,讓各位朋友對系統架構設計有更深刻的認識!

假設我們作了一個線上書店的網站,因為需要符合客戶快速進入市場的需求,所以在一開始的系統架構設計是採取相當簡單且常見的Three-tier設計,以Tiers & Layers diagram來說,將會是以下內容

常見的Three-tiers架構設計,以Tiers & Layers diagram為例

以佈署圖(Deployment Diagram)來看的話,就可以更明確地看到整個系統的元件各自是放在哪個機器上

常見的Three-tiers架構設計,以佈署圖為例
takeshi通常是在系統架構不大的時候,採用tiers & layers diagram便收工了;但當系統所處的環境越來越複雜時,就會採用佈署圖來作描述,如此可以更明確地表達想法和增進團隊的溝通。

接著如果客戶的線上書店網站系統,希望提供iPhone和Android app的話,系統架構又要怎麼設計才好呢?takeshi的想法是採用Multi-tier架構設計,如下圖所示

常見的Multi-tiers架構設計,以佈署圖為例


以上的架構設計跟Three-tier設計的最大差別是,把線上網路書店系統拆分成五個部分,分別條列如下

1. On-line Bookstore services
集中統一處理系統的商業邏輯,並且對外提供不同的存取介面(EJB, Webservice等)供不同使用者介面呼叫

2. On-line Bookstore web
供瀏覽器存取的使用者介面(UI, User Interface)

3. iPhone On-line Bookstore app
供iPhone存取的UI

4. Android On-line Bookstore app
供Android Phone存取的UI

 5. mySQL-5.5.x
統一資料庫

takeshi認為Multi-tier架構設計的顯而易見的好處在於...

1. 集中商業邏輯統一處理
使用者使用不同的UI (Web、iPhone、Android等),但背後系統的商業邏輯都是一致的;例如使用者選購書籍並下訂單,並不會因為使用UI的不同而有所不同(你並不會因為使用iPhone就可以不用挑選書籍,它不會聰明到幫你挑吧 XD);所以集中商業邏輯統一處理可以讓商業邏輯不會到處發散,也不會到處重複;當然這跟系統設計師(SD, System Designer)的設計能力也有關係啦...

然而UI的頁面和流程會有所不同,這就是每個UI的系統元件要去處理的事囉!

2. 不同角色的系統元件關係在實體邏輯上切分清楚
如果套入tiers的觀念來看待On-line Bookstore web、iPhone On-line Bookstore app和Android On-line Bookstore app系統元件的話,不難發現它們都屬於presentation tier,而On-line Bookstore services則屬於Biz Logic tier和Data Integration tier;所以Multi-tier的架構設計,能夠在系統實體配置上突顯出系統中不同元件所扮演的不同角色;且在溝通介面設計良好的情況下,在更改其中一個系統元件的實作時,不會影響到其它元件;再者,不同的元件被佈署在不同的Server上,可以增加錯誤排除的效率(透過log和Server控管介面等)等

Multi-tier的另外一個更重要的好處,就是 可以透過水平式擴展(Horizontally Scalable,也就是叢集(cluster)啦)的方式,來增加系統的scalability、Availability等;舉以下一些例子

1. 線上書店在上線一陣子之後,發現同時線上使用者人數越來越多而導致系統效率變差,經查詢Web Server的控管介面後發現,Web Server準備的request pool已經被過多的同時上線使用者給占光,導致Web Server必須等待空的request instance來服務使用者的請求,導致整體系統回應時間變長,然而request pool已無法再調大(已達機器上限);此時我們可以選擇新增一個機器來作為Web Server,這樣系統會有兩個Web Server組成的cluster來對外提供服務,這樣一來並能有效處理同時線上使用者人數越來越多的問題。

2. 如上例,線上書店在上線一陣子之後,發現透過Web Server和Smart phone設備的同時線上使用者人數越來越多而導致系統效率變差,經查詢Application Server(AP Server)控管介面後,發現是AP Server運算資源不足,我們同樣地可以考慮再加上一台機器,作為新的AP Server,這樣系統會有兩個AP Server組成的cluster來對外提供服務,這樣一來並能有效處理同時線上使用者人數越來越多的問題。

3.當系統的Web Server或是AP Server突然crash時,cluster中的另一台Server仍可持續運作,雖然系統的效率會降低(直到修復為止),但仍然可以持續提供服務,可以確保系統的availability。

傳統上為了要加強系統的非功能性需求的強度,通常是採取垂直式擴展(Vertical Scalable) ,也就是對一台機器狂加CPU和Memory,亦或是直接換一台更貴的機器來替代;至於要採用哪一種解決方案,需要從成本和技術能力上來作思考,水平式擴展方案的好處是可以使用相當便宜的機器,來組成一個cluster來提供服務;然而要達到前者所提供的運算能力,在垂直式擴展的方案來說,可能需要上百萬元等級的伺服器,才能達到同等級的運算能力。以技術能力來說,以Java平台來說,AP Server要組成cluster其實已經比以前要簡單很多,通常要注意的是AP Server的cluster設定、網路卡等級和路由器等級等;像上圖的AP Server是glassfish,是takeshi相當喜愛的AP Server,它是Oracle的opensource AP server,既免錢能力又強ㄛ(要作cluster也沒問題ㄛ),強力推薦!

takeshi認為阻礙系統水平式擴展的最大問題,其實仍然是開發團隊對系統的設計和實作方式啦...

就以上takeshi的描述提出下圖

常見的Multi-tiers + clusters架構設計,以佈署圖為例
講到這裡,大家應該有發現到takeshi一直沒有提到Database的cluster應該要怎麼作處理?其實相對於上述提及的Web Server和AP Server的水平式擴展(Scale-out),takeshi認為Database的Scale-out難度更是高很多;畢竟使用者需要自動化資訊系統,其主要用意也是希望可以更輕鬆的存取和操作資料,所以如何保持資料讀寫的一致性是非常重要的課題(會把資料弄壞的資訊系統,還會有人敢用嗎?);然而要如何在維持資料讀寫的一致性和水平式擴展之間取得平衡點,就是個相當具有挑戰的議題囉!

雖然takeshi不是資料庫管理的專家 ,但仍然可以藉助google大神的力量跟大家作一些分享啦...以下簡述一般關聯式資料庫(RDB, Relational Database)如何採取水平式擴展的方法 (當然朋友們也可以直接採取垂直式擴展的方式啦)

1. 讀寫分離 (主從複製,Master/Slave)
使用多台RDB組成一cluster,一台為Master,其它台為Slave,Master Server負責寫入(write)操作,其它Slave Server負責讀取(read)操作;此概念是基於資料庫的使用,通常是讀取操作的比率比寫入操作要來得高 (例如,讀取線上書店產品的機率,比使用者下訂單要來的高;假如一樣高的話,書店老闆就賺到合不嚨嘴啦 XD);概觀如下圖所示

RDB的水平式擴展方案,讀寫分離
2. 分庫 (Vertical Partitioning)
通常在讀寫分離也不符合需求的情況下,就要考慮分庫的作法了 (也就是被逼的啦...);同樣也是舉線上書店的案例,通常線上書店在關聯式模型(Relational Model)的設計下,可能會有客戶資訊、交易資訊和產品類別與庫存等表格,假設今天線上書店的生意超級興隆,導致以上表格的資料量大到已經塞不下在一台Master Server裡了!所以系統維運團隊就不得不採取分庫的方法,來維持線上書店系統的正常運作了。

分庫的概念很簡單,其實就是把資料量大的表格分別拆到不同的DB Server中,以上述案例來說,就是把客戶資訊、交易資訊和產品分類與庫存資訊的表格,分別放置在不同的DB Server中;概觀如下圖所示

RDB的水平式擴展方案,分庫
 另一種方式是把讀寫分離和分庫兩個方法結合在一起,此方法適用於即使已使用分庫方法,但查詢(讀取)效率仍然低落的清況;例如以上案例,產品分類與庫存的表格儲存了相當大筆的資料,雖然可以把這些表格裝在一台DB Server裡,但查詢效率仍有待提升,所以可以只針對產品分類與庫存的表格作讀寫分離的作法;概觀如下圖所示,重點在右下台DB Server中

RDB的水平式擴展方案,分庫 + 讀寫分離
 3. 分庫 + 分表 (Horizontal Partitioning/Database sharding)
 通常在使用了分庫作法也還是不符合需求的情況下,就要考慮分庫分表的作法了 (走到這個地步的話,takeshi真的要恭喜,表示這間公司真的賺很大ㄚ...Orz);同樣如上案例,假使作了分庫之後,產品分類與庫存表格的資料量仍然大到一台DB Server無法承受,此時就需要作分表了。

概念上同樣也很簡單,就是把原來的一張表格,拆分成多張表格啦;概觀如下圖所示,重點是在DB Server4中的表格,是從DB Server3的表格中拆分出來的
RDB的水平式擴展方案,分庫+分表
以上的RDB水平式擴展的方案,還是屬於較概念上的描述,實際上還是要看各家DB產品的支援和解決方案為主啦;但不可否認的是,從一個架構遷移到另一個架構,都是相當耗費時間和人力的大工程,也需要有相當經驗的DBA來協助,此遷移才能順利完成;此外,RDB這段落是takeshi從網路上的文章所整理下來,所以應該跟實務上的作法仍有一些差距,這就看看有沒有熱心的網友提供建議囉 XD

近年來相當火紅的noSQL DB,也是為了要解決上述等等問題而產生的;據takeshi的了解,hadoop的目的是在提供資訊系統一個可以無限水平擴展分散式檔案系統;HBase則是基於Hadoop,可以無限水平擴展分散式資料庫;另外還有Memcached這類的分散式memory database,用來緩存系統常用的資訊,以進而增加系統的反應時間;總而言之,noSQL DB的產品可是不勝枚舉ㄚ...對超大規模資訊系統架構設計有興趣的朋友,也可以參考High Scalability這個網站,takeshi有時候也會上去晃晃說

這篇文章到這裡也夠長了,takeshi之後有機會再說說noSQL的感想唄~