各种状态管理的对比与总结
前面分别介绍了ASP.NET的8种状态管理技术,这里打算给它们做个总结。
客户端 | 服务端 | |
数据安全性 | 差 | 好 |
数据长度限制 | 有 | 受硬件限制 |
占用服务器资源 | 否 | 是 |
集群扩展性 | 好 | 差 |
表格中主要考察了数据保存与服务端水平扩展的相关重要指标。
下面我来解释表格的结果。
1. 客户端方式的状态数据(hidden-input, QueryString, Cookie):
a. 数据对用户来说,可见可修改,因此数据不安全。
b. QueryString, Cookie 都有长度限制。
c. 数据在客户端,因此不占用服务端资源。这个特性对于在线人数很多的网站非常重要。
d. 数据在客户端,因此和服务端没有耦合关系,WEB服务器可以更容易实现水平扩展。
2. 服务端方式的状态数据(ApplicationState,ViewState,ControlState,Session,Profile):
a. 数据对用户不可见,因此安全性好。(ApplicationState,Session,Profile)
b. 数所长度只受硬件限制,因此,对于在线人数较多的网站,需谨慎选择。
c. 对于存放在内存中的状态数据,由于不能共享内存,因此会限制水平扩展能力。
d. 如果状态数据保存到一台机器,会有单点失败的可能,也会限制了水平扩展能力。
从这个表格我们还可以得到以下结论:
1. 如果很关注数据的安全性,应该首选服务端的状态管理方法。
2. 如果你关注服务端的水平扩展性,应该首选客户端的状态管理方法。
会话状态的选择
接下来,我们再来看看会话状态,它与状态管理有着一些关系,属于比较类似的概念。
谈到会话状态,首先我要申明一点:会话状态与状态不是一回事。
本文前面所说的状态分为二种:
1. 页面之间的状态。
2. 应用程序范围内的状态。
而会话状态是针对某个用户来说,他(她)在多次操作之间的状态。
在用户的操作期间,有可能状态需要在页面之间持续使用,
也有可能服务端程序做过重启,但数据仍然有效。
因此,这种状态数据更持久。
在ASP.NET中,使用会话状态有二个选择:Session 或者 Cookie 。
前者由ASP.NET实现,并有可能依赖后者。
后者则由浏览器实现,ASP.NET提供读写方法。
那么到底选择哪个呢?
如果你要问我这个问题,我肯定会说:我选 Cookie !
下面是我选择Cookie实现会话状态的理由:
1. 不会有服务端阻塞问题。
2. 不占用服务端资源。
3. 水平扩展没有限制。
4. 也支持过期设置,而且更灵活。
5. 可以在客户端直接使用会话数据。
6. 可以实现更灵活的会话数据加载策略。
7. 扩展性较好(源于ASP.NET管线的扩展性)
如果选择使用Cookie实现会话状态,有3点需要特别注意:
1. 不建议保存敏感数据,除非已加密。
2. 只适合保存短小简单的数据。
3. 如果会话数据较大,可以在客户端保存用户标识,由服务端实现数据的加载保存逻辑。
或许有些人认为:每种技术都有它们的优缺点,有各自的适用领域。
我表示赞同这句话。
但是,我们要清楚一点:每个项目的规模不一样,性能以及扩展性要求也不同。
对于一个小的项目来说,选择什么方法都不是问题,
但是,对于规模较大的项目,我们一定需要取舍。
取舍的目标是:包装越少越好,因为人家做了过多的包装,就会有较多的限制,
所以,不要只关注现在的调用是否方便,其实只要你愿意包装,你也可以让复杂的调用简单化。
改变开发方式,发现新方法
回想一下:为什么在ASP.NET中需要状态管理?
答:因为与HTTP协议有关,服务端没有保存每个请求的上次页面状态。
为什么Windows计算器(这类)程序不用考虑会话问题呢?
答:因为这类程序的界面不需要重新生成,任何变量都可表示状态。
再来看这样一个场景:
图片左边是一个列表页面,允许调整每条记录的优先级,但是有2个要求:
1. 在移动每条记录时,必须输入一个调整理由。
2. 只要输入理由后,那条记录可以任意调整多次。
显然,完成这个任务必须要有状态才能实现。
面对这个问题,你可以思考一下:选择哪种ASP.NET支持的状态管理方法都很麻烦。
怎么办?
我的解决方法:创建一个JavaScript数组,用每个数组元素保存每条记录的状态,
所有用户交互操作用AJAX方式实现,这样页面不会刷新,JavaScript变量中的状态一直有效。
因此,很容易就能解决这个问题。
这个案例也提醒我们:当发现ASP.NET提供的状态管理功能全部不合适时, 我们需要改变开发方式了。
为什么WEB编程都有【无状态】问题,而桌面程序没有?
我认为与HTTP协议有关,但没有绝对的关系。
只要你能保证页面不刷新,也能像桌面程序那样,用JavaScript变量就能维护页面状态。