各種狀態(tài)管理的對比與總結(jié)
前面分別介紹了ASP.NET的8種狀態(tài)管理技術(shù),這里打算給它們做個總結(jié)。
客戶端 | 服務(wù)端 | |
數(shù)據(jù)安全性 | 差 | 好 |
數(shù)據(jù)長度限制 | 有 | 受硬件限制 |
占用服務(wù)器資源 | 否 | 是 |
集群擴(kuò)展性 | 好 | 差 |
表格中主要考察了數(shù)據(jù)保存與服務(wù)端水平擴(kuò)展的相關(guān)重要指標(biāo)。
下面我來解釋表格的結(jié)果。
1. 客戶端方式的狀態(tài)數(shù)據(jù)(hidden-input, QueryString, Cookie):
a. 數(shù)據(jù)對用戶來說,可見可修改,因此數(shù)據(jù)不安全。
b. QueryString, Cookie 都有長度限制。
c. 數(shù)據(jù)在客戶端,因此不占用服務(wù)端資源。這個特性對于在線人數(shù)很多的網(wǎng)站非常重要。
d. 數(shù)據(jù)在客戶端,因此和服務(wù)端沒有耦合關(guān)系,WEB服務(wù)器可以更容易實(shí)現(xiàn)水平擴(kuò)展。
2. 服務(wù)端方式的狀態(tài)數(shù)據(jù)(ApplicationState,ViewState,ControlState,Session,Profile):
a. 數(shù)據(jù)對用戶不可見,因此安全性好。(ApplicationState,Session,Profile)
b. 數(shù)所長度只受硬件限制,因此,對于在線人數(shù)較多的網(wǎng)站,需謹(jǐn)慎選擇。
c. 對于存放在內(nèi)存中的狀態(tài)數(shù)據(jù),由于不能共享內(nèi)存,因此會限制水平擴(kuò)展能力。
d. 如果狀態(tài)數(shù)據(jù)保存到一臺機(jī)器,會有單點(diǎn)失敗的可能,也會限制了水平擴(kuò)展能力。
從這個表格我們還可以得到以下結(jié)論:
1. 如果很關(guān)注數(shù)據(jù)的安全性,應(yīng)該首選服務(wù)端的狀態(tài)管理方法。
2. 如果你關(guān)注服務(wù)端的水平擴(kuò)展性,應(yīng)該首選客戶端的狀態(tài)管理方法。
會話狀態(tài)的選擇
接下來,我們再來看看會話狀態(tài),它與狀態(tài)管理有著一些關(guān)系,屬于比較類似的概念。
談到會話狀態(tài),首先我要申明一點(diǎn):會話狀態(tài)與狀態(tài)不是一回事。
本文前面所說的狀態(tài)分為二種:
1. 頁面之間的狀態(tài)。
2. 應(yīng)用程序范圍內(nèi)的狀態(tài)。
而會話狀態(tài)是針對某個用戶來說,他(她)在多次操作之間的狀態(tài)。
在用戶的操作期間,有可能狀態(tài)需要在頁面之間持續(xù)使用,
也有可能服務(wù)端程序做過重啟,但數(shù)據(jù)仍然有效。
因此,這種狀態(tài)數(shù)據(jù)更持久。
在ASP.NET中,使用會話狀態(tài)有二個選擇:Session 或者 Cookie 。
前者由ASP.NET實(shí)現(xiàn),并有可能依賴后者。
后者則由瀏覽器實(shí)現(xiàn),ASP.NET提供讀寫方法。
那么到底選擇哪個呢?
如果你要問我這個問題,我肯定會說:我選 Cookie !
下面是我選擇Cookie實(shí)現(xiàn)會話狀態(tài)的理由:
1. 不會有服務(wù)端阻塞問題。
2. 不占用服務(wù)端資源。
3. 水平擴(kuò)展沒有限制。
4. 也支持過期設(shè)置,而且更靈活。
5. 可以在客戶端直接使用會話數(shù)據(jù)。
6. 可以實(shí)現(xiàn)更靈活的會話數(shù)據(jù)加載策略。
7. 擴(kuò)展性較好(源于ASP.NET管線的擴(kuò)展性)
如果選擇使用Cookie實(shí)現(xiàn)會話狀態(tài),有3點(diǎn)需要特別注意:
1. 不建議保存敏感數(shù)據(jù),除非已加密。
2. 只適合保存短小簡單的數(shù)據(jù)。
3. 如果會話數(shù)據(jù)較大,可以在客戶端保存用戶標(biāo)識,由服務(wù)端實(shí)現(xiàn)數(shù)據(jù)的加載保存邏輯。
或許有些人認(rèn)為:每種技術(shù)都有它們的優(yōu)缺點(diǎn),有各自的適用領(lǐng)域。
我表示贊同這句話。
但是,我們要清楚一點(diǎn):每個項(xiàng)目的規(guī)模不一樣,性能以及擴(kuò)展性要求也不同。
對于一個小的項(xiàng)目來說,選擇什么方法都不是問題,
但是,對于規(guī)模較大的項(xiàng)目,我們一定需要取舍。
取舍的目標(biāo)是:包裝越少越好,因?yàn)槿思易隽诉^多的包裝,就會有較多的限制,
所以,不要只關(guān)注現(xiàn)在的調(diào)用是否方便,其實(shí)只要你愿意包裝,你也可以讓復(fù)雜的調(diào)用簡單化。
改變開發(fā)方式,發(fā)現(xiàn)新方法
回想一下:為什么在ASP.NET中需要狀態(tài)管理?
答:因?yàn)榕cHTTP協(xié)議有關(guān),服務(wù)端沒有保存每個請求的上次頁面狀態(tài)。
為什么Windows計(jì)算器(這類)程序不用考慮會話問題呢?
答:因?yàn)檫@類程序的界面不需要重新生成,任何變量都可表示狀態(tài)。
再來看這樣一個場景:
圖片左邊是一個列表頁面,允許調(diào)整每條記錄的優(yōu)先級,但是有2個要求:
1. 在移動每條記錄時,必須輸入一個調(diào)整理由。
2. 只要輸入理由后,那條記錄可以任意調(diào)整多次。
顯然,完成這個任務(wù)必須要有狀態(tài)才能實(shí)現(xiàn)。
面對這個問題,你可以思考一下:選擇哪種ASP.NET支持的狀態(tài)管理方法都很麻煩。
怎么辦?
我的解決方法:創(chuàng)建一個JavaScript數(shù)組,用每個數(shù)組元素保存每條記錄的狀態(tài),
所有用戶交互操作用AJAX方式實(shí)現(xiàn),這樣頁面不會刷新,JavaScript變量中的狀態(tài)一直有效。
因此,很容易就能解決這個問題。
這個案例也提醒我們:當(dāng)發(fā)現(xiàn)ASP.NET提供的狀態(tài)管理功能全部不合適時, 我們需要改變開發(fā)方式了。
為什么WEB編程都有【無狀態(tài)】問題,而桌面程序沒有?
我認(rèn)為與HTTP協(xié)議有關(guān),但沒有絕對的關(guān)系。
只要你能保證頁面不刷新,也能像桌面程序那樣,用JavaScript變量就能維護(hù)頁面狀態(tài)。
本文導(dǎo)航
- 第1頁: 首頁
- 第2頁: QueryString
- 第3頁: Cookie
- 第4頁: ApplicationState
- 第5頁: Session
- 第6頁: Profile
- 第7頁: 各種狀態(tài)管理對比