最近台鐵的 訂票系統 被 搶票程式 弄得幾乎癱瘓,再遠一點,舞台劇歌劇魅影的售票系統也在大量購票者湧入而出現幾乎停擺的狀況,不禁讓人對以三層式架構設計的系統是否有能力處理瞬間大量連線感到懷疑,本文就大同大學在開發負載平衡式選課系統時所面臨的問題及解決方案,討論我們如何聯合多台一般的PC伺服器來提供瞬間大量連線的服務,以及在面臨學生利用外掛程式搶課時的應變方案,希望能藉此拋磚引玉,各方專家可以將自己的私房密笈公諸於世,讓類似被搶票程式弄得幾近癱瘓的狀況盡量不要再發生。
負載平衡伺服器是關鍵
瀏覽器--應用伺服器--資料庫伺服器的三層式架構是目前網際網路應用系統開發最流行的方式,用戶端利用瀏覽器連結到應用伺服器,應用伺服器藉由存取後端資料庫伺服器之資料完成用戶所要求的任務並將結果回應給用戶端,這種系統最大的好處是用戶端只要有瀏覽器即可,避免需要在用戶端安裝程式所衍生出來之繁雜問題,在連線數量低時,這種系統相當好用,可是一旦連線數變大時,常會有系統反應變慢的問題,此時用戶又常會因急於完成交易而不斷地按送出按鈕,讓更多的連線要求湧入,終致系統癱瘓。
瞬間出現大量連線狀況可能出現在長假期前海陸空運訂票系統、熱門表演節目的售票系統以及大專院校的線上選課系統,這些系統有一個共同的特色:僧多粥少,以本校的選課系統為例,最熱門的課程三秒鐘就選爆了,20秒內有大約有30門課程達到人數上限,搶課之兇可見一斑。有些機構為了應付這類狀況,投入鉅資購置高效能大型主機,當然,如果這類狀況是經常出現,這種投資還算值得,但如果像選課系統這類每年只發生少數幾次的需求,平時幾乎處於閒置狀態,投資就顯得有點浪費了,況且單一主機同時可提供的連線數還是有其限制,如果被進行阻斷服務攻擊(DoS),所提供的服務因為沒有替代系統,可能就此完全停擺,比較物美價廉的選擇,應該是利用負載平衡式應用伺服器架構來分攤大量連線的需求。
一般化之負載平衡系統透過分配器,用戶的連線會被導引給一台最適當的應用伺服器處理,如何選取最適當的應用伺服器是影響整個負載平衡系統效能最核心的關鍵,由文獻得知,分配器可能的實現方式主要有下列三種:
分配器的實現方式三種
1.採用Layer 7負載平衡器來分配用戶端連線至其所控管之多部應用伺服器。
2.透過DNS伺服器round-robin的處理,將各應用伺服器都指定成同一個FQDN (Full Qualified Domain Name),用戶端查詢時輪流提供不同的IP位址給用戶端。
3.讓一台或多台應用伺服器兼任分配器,各應用伺服器會向分配器或主資料庫登記自己當時的負載情況,分配器會依各應用伺服器的負載狀況將用戶連線導引到最適當之伺服器。
第一種方式中的負載平衡器價格並不低,出現瞬間大量連線時有可能變成瓶頸所在,應用伺服器的加入與退出也需要設定與調校,不過由於是現成的設備,如果平時連線數就頗大,機構也有充裕的經費和熟悉管理與設定之技術人員,應該是個不錯的選擇。
第二種方式需要配合DNS伺服器一起運作,雖然在應用伺服器端的DNS伺服器可以將TTL(Time to Life)的值設成0或是很小,以達到平衡效果,但有些中繼DNS伺服器會忽略掉設得太小之TTL值,造成藉由該DNS查詢網址的用戶端都會湧向同一台應用伺服器,造成負載不平衡現象。
第三種方式的彈性最大,也是我們所採行之架構,它甚至可以做到依地理區域來分配應用伺服器,達到廣域的負載平衡。以下我們就針對這種架構探討其中比較核心之技術。
收集負載資料需要藉助伺服器所提供之應用程式,以Linux為例,我們可用vmstat檢查記憶體大小與使用情形以及CPU的負載狀況,用netstat來檢查連線狀況,透過程式取得相關參數之後,由應用伺服器向分配器登錄,或由分配器每隔一段時間主動過來查詢,分配器依據這些數據以及CPU的等級來導引用戶端連結到最適當之應用伺服器,經過多次選課實戰經驗,這種方式可以相當均勻地依伺服器效能分配用戶之連線,達到不錯的負載平衡效果。
HTTP協定提供了一個網頁伺服器導引用戶端瀏覽器連到另一個網站的機制,稱為header redirection,不同的語言有不同的語法,以下就ASP, PHP以及JavaScript舉例說明:
ASP: Response.Redirect(“http://newsite/newscript”)
PHP: header(“Location: http://newsite/newscript”)
Javascript: location=http://newsite/newscript
除了以JavaScript來處理外,通常header必須放在其他資料輸出之前,否則有些系統會抱怨並以錯誤訊息收場,無法真正轉移,在使用時宜注意。
靜態資料存本機資料庫
應用伺服器可以結合多部機器透過負載平衡方式分攤大量連線,但後端的資料庫伺服器就沒這麼容易處理了,資料庫伺服器可能會因為沒有辦法負荷而拒絕連線造成交易失敗。一個可行的辦法是在每台應用伺服器上都安裝資料庫軟體,將靜態資料存在本機的資料庫中,會異動的資料才留在主資料庫裡,靜態資料包括行車的班表與座位配置表,表演的場次資料與座位表,選課系統的排課資料等,這些資料通常在尖峰時期不會改變,若妥善規劃應用軟體,將可以大量減少應用伺服器與儲存異動資料之主資料庫伺服器間的交易次數,降低主資料庫伺服器之負擔,讓系統可以承載更高的同時連線數。
接著我們來看看實際運作時可能會面臨的問題,如果用戶端利用程式來搶票或搶課時要怎麼處理呢?這是一個蠻令人頭痛的問題,在台鐵售票系統被搶票程式攻陷事件的後續報導中,有人建議限制同一個IP位址在一定時間內只能訂幾次票,這個解決辦法在下述情況會有問題,很多公司對外只有一個IP位址,公司裡所有的人都透過NAT伺服器用這個IP位址上網,另外有些大專院校因為可用IP位址較少,宿舍只能分配到少數幾個IP位址,透過NAT處理,讓全部的住宿生使用,另外有些機構或學校強制用戶一定要透過代理伺服器才能連上外部網站,這些狀況都會讓所建議之限制個別IP位址訂票次數的處理方式,妨礙到正常之訂票作業。即使要採用這種方式,限制的次數也應酌予放寬,最好是能由過去之訂票紀錄找出合理的數字。
可採身分識別碼控管
在處理程式搶課方面,我們基本上是對最近十分鐘內出現多次選課異常紀錄者直接將其登出,並將該生的帳號鎖定一段時間,避免學生利用程式又自動登入,台鐵訂票系統利用身分證字號做為登入識別碼,應該也可以採用類似的機制控管。
對於程式搶票的問題,也有人建議系統在用戶確認訂票時,以圖形方式顯示一些不易用程式判讀的數字或文字,並要求訂票者將那些字輸入做為驗證,這是一個相當不錯的處理方式,但會增加用戶在使用上的不便,至少在選課系統上不太適用,所以這種方式應該是沒有其他辦法時才用比較好。
當資源有限又有很多人要搶時,對於提供服務的系統來說絕對會造成沉重負擔,本文以售票及選課系統為例,介紹可以應付瞬間大量連線之負載平衡系統的實現方式,也探討在規劃與實現這類系統時所面臨到的問題及解決辦法,希望能對面臨到這類問題之系統規劃與程式設計人員有些幫助。
本文作者/大同大學資訊工程學系所主任包蒼龍
|