Asp.net 中的状态管理机制

什么是状态

要说状态管理机制,得先来说说 “状态” 是个什么玩意儿。怎么理解这个状态?这里举个例子:当你手机快没电的时候,你会发现这个手机的电源指示灯一亮一灭,这其实就是告诉你当前手机的状态变成了 “电量低” 。你一看见这个状态,就知道该充电了。换言之,状态就一堆信息,当你读懂这部分信息的时候,就会执行对应的操作。

再来举个例子,当你要发微博的时候,你得先登录吧? 不登录能不能发微博呢?这个答案显示是否定的。那为什么要登录呢?因为登录之后,才能知道当前这条微博是谁写的。那为什么登录之后,就知道是谁写的了呢?服务器又没和你见过面,凭什么能确定这条微博是你发的呢?那是因为你的成功登录,相当于手机电源指示灯由正常变成一亮一灭,也就是说有了一个状态,服务器看到这个状态就明白这条微博是你发的了。


明白了状态,再来说说状态管理

微博是通过http协议把数据在你家和服务器之间进行点对点传送的,服务器要想知道你的状态就必须通过http协议。可惜,不巧的是HTTP是个无状态的协议。也就是说就算你成功登录了,Http协议也没法记住这个状态,这样下次你和服务器进行通信的时候,服务器仍旧会把你当成陌生人,相当于手机没有电源指示灯(那自然就看不出是否没电了)。

于是就有了下文中要说的各种状态管理机制(这里所罗列的只是本人在开发中所用到过的,可能并不完整)。


首先来看客户端的几种方式

类别大小限制生命周期

与会

(Session)相关

保存的位置是否序列化适用情况注意

可持久化

Cookie

4K(大多数浏览器)在指定时间内持久化保存否,但是特定于单个用户客户端硬盘当你希望在客户端保存少量数据且不是很在意安全性的时候不同的电脑不能共享,安全性低

会话

Cookie

4K(大多数浏览器)会话生命周期是,同时特定于单个用户客户端硬盘

ViewState小量,简单数据类型一个Web页面的生命周期否,特定于单个页面客户端页面Webform中用于维护同一个页面的状态,如Postback
隐藏域小量,简单数据类型一个Web页面的生命周期否,特定于单个页面客户端页面


服务器端状态管理

类别大小限制生命周期

与会

(Session)相关

保存的位置是否序列化适用情况注意
Application无限制Web应用程序生命周期否,所有Web会话共享Web应用程序的内存当需要被不同的会话共享,且不经常变化的数据

1. 数据太多的时候,会迅速耗尽服务器内存。

2. 多台web服务器之间不能共享 application。

3. 并发时需要手动加锁。

4. 服务器当机,所有状态丢失。

Cache无限制可以手动设置缓存时间及相关属性,当在系统内存吃紧的时候会根据这些属性对Cache进行清理否,所有Web会话共享Web应用程序的内存

Session

[InProc]

小量,简单数据类型用户的活动时间+一段延迟(一般为20分钟)是,特定于单个用户会话Web应用程序的内存同个会话不同页面间有传值需求、数据生命周期短、特定于某一个会话。由于存放在Web应用程序的内存中,因此不同的web服务器无法共享状态。

Session

[StateServer]

小量,简单数据类型用户的活动时间+一段延迟(一般为20分钟)是,特定于单个用户会话Asp.net状态管理进程
多台web服务器可以共享状态

Session

[SqlServer]

小量,简单数据类型用户的活动时间+一段延迟(一般为20分钟)是,特定于单个用户会话Sql Server
多台web服务器可以共享状态



基本操作

1. Application

继承自 HttpApplicationState 类,其实例在客户端第一次请求 Web 应用程序时创建。


添加缓存

Application["msg"] = "welcome"; //如果没有msg缓存,则创建一个新的,否则修改原来的。key 不区分大小写
Application.Add("msg","welcome");//2种方式效果一样

因为Application中存储的是没有序列化的对象,所以当保存的是一个引用类型的实例,比如一个数组,后续往数组中加入一个值后,则Application中的值也会发生相应的变化。


读取

string str = Application["msg"] as string;


修改

Application["msg"] = "123";
Application.Set("msg","123");


删除

Application.Remove("msg");
Application.RemoveAll();
Application.Clear();//和RemoveAll完全一样



2. Cache (System.Web.Caching)


添加

Cache["msg"]="welcome"; //如果已经存在则覆盖,否则创建,key 区分大小写

//Add 方式会返回新添加的对象,如果已经存在,则不覆盖。
Cache.Add("msg", "welcome", null, Cache.NoAbsoluteExpiraion, Cache.NoSlidingExpiration, Caching.CacheItemPriority.Normal, null);

//无返回值,如果已经存在,则覆盖。
Cache.Insert("msg", "welcome");

因为Cache中存储的是没有序列化的对象,所以当保存的是一个引用类型的实例,比如一个数组,后续往数组中加入一个值后,则Cache中的值也会发生相应的变化。


读取

string str = Cache["msg"] as string;


修改

无法修改,只能被覆盖


删除

Cache.Remove("msg");



3. Session

继承自 HttpSessionState 类,当一用户首次向Web应用程序发起一次请求,Web 应用程序便为这个用户创建了一个session。默认情况下,只要用户持续不断地访问这个web应用程序,那么 session 就会一直存在。如果当用户关闭浏览器,则 session 就失效了,或者用户不再向 web 应用程序发起任何请求时,超过20分钟,那么session也就自动失效了。


添加

Session["msg"] = "123"; //如果已经存在则覆盖,否则创建,key 不区分大小写。
Session.Add("msg","123"); //和上句效果一样

因为Cache中存储的是没有序列化的对象,所以当保存的是一个引用类型的实例,比如一个数组,后续往数组中加入一个值后,则Cache中的值也会发生相应的变化。


读取

string str = Session["msg"] as string;


修改

Session["msg"] = "234";


删除

Session.Remove("msg");
Session.RemoveAll();
Session.Clear(); //与 RemoveAll 一样


使当前的Session失效

Session.Abandon();

InProc的模式下,Session_End 将被触发。那么下次对这个 web 应用程序的请求将会触发一个新的Session(SessionId可能使用旧的);单纯的关闭浏览器,Session_End 不会触发。只有当Session因为生命周期结束或者调用 Session.Abandon 时才会触发。


一般在 Session 超时或删除之后,SessionID保持不变,因为Session过期后,服务器端会清除数据,但是 SessionID 保存在客户端(Session Cookie 中),所以只要浏览器不关闭则 Http 头中的SessionID就保持不变。

Session_End 是由独立线程触发的,所以在 Session_End 中无法使用 HttpContext 对象,即无法使用 Response.Redirect 和 Server.Transfer 等方法。

Session 默认为 InProc, 保存在进程中,但这个进程不稳定,可能会导致存储在进程内的值意外丢失。

导致进程不稳定的几种原因:1. 配置文件中 ProcessModel 标签的 memoryLimit 属性。2. Global.asax 或者 Web.Config 文件被更改。 3. Bin 文件夹中的Web程序被修改。4. 杀毒软件扫描了一些.config文件。


4. Cookie

    Cookie是 Web 应用程序在用户硬盘上存放的一段包含键值对的文本。

Response.Cookie["msg"].Value = "welcome"


更多资源

ASP.NET State Management Recommendations

文章索引

[隐 藏]

本站采用知识共享署名 3.0 中国大陆许可协议进行许可。 ©2014 Charley Box | About Site | 浙ICP备13014059号