怎么使用Session本身的问题,这个就不必多说了吧。在这里就谈谈Session的管理机制。ASP.NET的优秀之处就在于它能充分利用整个.NET框架所提供的优秀的基础结构和底层操作,而大量设计模式的应用则大大加强了ASP.NET的可扩展性和可伸缩。当然在Session的管理方面.NET框架也同样为其提供了巨大的灵活性和可扩展性。

ASP.NET为Session的管理提供了5种可选模式(基于Provider模型):1.不使用(Off),2.进程内(InProc),3.状态服务器(StateServer),4.SQLServer数据库(SQLServer),5.自定义(Custom)。默认情况下ASP.NET使用进程内模式管理Session状态。一般情况下基于小型应用的ASP.NET网站使用进程内管理Session状态已经足够了。如果我们需要在一个拥有多个子网站频道的大型网站中使用Session状态管理,那我们就需要考虑使用状态服务器或SQLServer的模式来管理Session的状态了。同样的需求也可能出现在负载均衡情况下的网站群集条件中。关于如何使用状态服务器或SQLServer的模式来管理大型网站的Session状态的介绍和使用详细在这里也就不具体介绍说明了,感兴趣的话可以参考MSDN文档或各位大牛的技术博文。^-^

在一年前的一个项目中我遇到如此情景,项目是由一个主体频道站点和多个子频道站点组成。项目中有关用户的管理被设计到一个单独用户管理中心站点统一管理。鉴于之上的设计需求管理整个站点的Session状态我自然而然就想到需要使用状态服务器或SQLServer的模式来实现Session共享。于是参考了一段时间MSDN文档后决定使用状态服务器来实现(同时也由于项目本身自己的一些特点)。于是兴致勃勃的继续着之后的设计,但当项目即将交付的时候却被告知当前生产环境中只有三台服务器可供项目部署。由于当初参考MSDN文档的时候我清楚的记得使用状态服务器管理Session状态时,在IIS托管的网站及子网站都需要相同的网站标识符才能在状态服务器中定位正确的Session状态对象,而现在多个网站可能需要被部署到同一台机器的同一个IIS中,大家都知道每个IIS中的网站标识符都是唯一的。这下子我犯难了,于是苦思冥想了整整2天时间,最后想到了下面这个另类用法来解决此问题。

由于框架为我提供的状态服务器模式不能满足我的要求,因此我需要使用自定义Session管理模式。用于拦截IIS向状态服务器请求的消息,模拟所有频道站点的请求都使用相同的网站标识符。在这里我按照Session管理的提供者扩展模型实现了一个自定义的Session管理类,用来给系统提供的状态服务器管理类做一个对象适配,在内部同过反射技术来创建一个System.Web.SessionState.OutOfProcSessionStateStore类的对象实例并修改对象的部分属性来满足项目的需求,代码类定义如下:

Code
//本类使用对象适配器模式修改系统默认设置,使单个IIS中多个应用程序共用同一状态session
    public class CustomOutOfProcSessionStateStore : SessionStateStoreProviderBase
    {
        private SessionStateStoreProviderBase _sessionStateStore = null;

        public OutOfProcSessionStateStore()
        {
            Assembly assembly = Assembly.GetAssembly(typeof(System.Web.SessionState.HttpSessionState));
            _sessionStateStore = 
                (SessionStateStoreProviderBase)assembly.CreateInstance("System.Web.SessionState.OutOfProcSessionStateStore");
        }

        public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
        {
            _sessionStateStore.Initialize(name, config);

            Type storeType = _sessionStateStore.GetType();
            //系统指定默认路径变量名称
            string baseUriName = "s_uribase";
            //获取系统默认路径设置
            string oldBaseUri = (string)storeType.InvokeMember(baseUriName, 
                BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Static,
                null, 
                null, 
                new object[] { }
                );
            //指定系统ApplicationId,这里的888就是IIS中的网站标识符
            string appId = "/LM/W3SVC/888/ROOT";
            //获取配置加密key
            string hashKey = (string)typeof(System.Web.Configuration.MachineKeySection).InvokeMember("HashAndBase64EncodeString", 
                BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Static,
                null, 
                null, 
                new object[] { appId }
                );
            //获取新的session检索基路径
            string newBaseUri = appId + "(" + hashKey + ")/";
            //修改系统默认路径设置
            storeType.InvokeMember(baseUriName,
                BindingFlags.SetField | BindingFlags.NonPublic | BindingFlags.Static, 
                null, 
                null, 
                new object[] { newBaseUri }
                );

            base.Initialize(name, config);
        }

        public override SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout)
        {
            return _sessionStateStore.CreateNewStoreData(context, timeout);
        }

        public override void CreateUninitializedItem(HttpContext context, string id, int timeout)
        {
            _sessionStateStore.CreateUninitializedItem(context, id, timeout);
        }

        public override void Dispose()
        {
            _sessionStateStore.Dispose();
        }

        public override void EndRequest(HttpContext context)
        {
            _sessionStateStore.EndRequest(context);
        }

        public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions)
        {
            return _sessionStateStore.GetItem(context, id, out locked, out lockAge, out lockId, out actions);
        }

        public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions)
        {
            return _sessionStateStore.GetItemExclusive(context, id, out locked, out lockAge, out lockId, out actions);
        }

        public override void InitializeRequest(HttpContext context)
        {
            _sessionStateStore.InitializeRequest(context);
        }

        public override void ReleaseItemExclusive(HttpContext context, string id, object lockId)
        {
            _sessionStateStore.ReleaseItemExclusive(context, id, lockId);
        }

        public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item)
        {
            _sessionStateStore.RemoveItem(context, id, lockId, item);
        }

        public override void ResetItemTimeout(HttpContext context, string id)
        {
            _sessionStateStore.ResetItemTimeout(context, id);
        }

        public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem)
        {
            _sessionStateStore.SetAndReleaseItemExclusive(context, id, item, lockId, newItem);
        }

        public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback)
        {
            return _sessionStateStore.SetItemExpireCallback(expireCallback);
        }
    }

整个类中最重要的方法是Initialize方法,其他的只是做一下简单的对象方法适配以保证和框架提供的类保持相同的逻辑功能。其实在整个拦截过程中我们只需要修改baseUriName的值,如何修改baseUriName的值已经在类的方法定义中做了注释说明,大家可以参照类型定义了解详细。

类型定义好以后我们需要做的代码工作就完毕了,接下来要做的只是把这个类型引入到各个频道站点项目下,当然也可以直接把类型复制到AppCode目录下,也可以把它单独放在一个程序集中单独编译并引用到各个频道站点项目下。 接下我们需要做的工作就是修改各个站点下Web.Config文件中的Session配置节点,配置如下:

<sessionState 
    mode="Custom" 
    cookieless="false" 
    timeout="15" 
    stateConnectionString="tcpip=ip:端口" 
    customProvider="OutOfProcSessionProvider" 
    stateNetworkTimeout="300">
    <providers>
       <add name="OutOfProcSessionProvider" type="CustomOutOfProcSessionStateStore"/>
    </providers>
</sessionState>

在这里特别要注意的是我们还需要添加machineKey配置节用来在Initialize方法中使用相同的key值重新加密解密ApplicationId。

<machineKey  
 validationKey="78AE3850338BFADCE59D8DDF58C9E4518E7510149C46142D7AAD7F1AD49D95D4"  
 decryptionKey="5FC88DFC24EA123C"
 validation="SHA1"/>

最后在各个站点中执行相同的配置过程就可以实现同一IIS中用状态服务器模式实现Session状态共享了。^-^

当然如果以后条件许可下,我们只需要简单的修改下配置就能把Session管理还原到框架提供的状态服务器管理模型中,非常之方便!

转载于:https://www.cnblogs.com/igtea/archive/2009/02/03/1382825.html

ASP.NET Trick文章系列--使用State Server管理Session状态的另类经济用法相关推荐

  1. Asp.net MVC2.0系列文章-编辑和删除新闻操作

    上一篇文章,我们简单地完成了新闻内容的展示功能(Asp.net MVC2.0系列文章-显示列表和详细页面操作),此篇文章,我们使用Asp.net MVC2.0实现新闻记录的编辑和删除功能. 创建Vie ...

  2. 在发布ASP.NET网站的时候,出现state server错误

    错误信息如下: 在发布ASP.NET网站的时候,出现state server错误: Server Error in '/' Application. ------------------------- ...

  3. 基于DDD的现代ASP.NET开发框架--ABP系列文章总目录(转)

    出处:http://www.cnblogs.com/mienreal/p/4528470.html ABP相关岗位招聘:给热爱.NET新技术和ABP框架的朋友带来一个高薪的工作机会 ABP交流会录像视 ...

  4. 基于DDD的现代ASP.NET开发框架--ABP系列文章总目录

    ABP相关岗位招聘:给热爱.NET新技术和ABP框架的朋友带来一个高薪的工作机会 ABP交流会录像视频:ABP架构设计交流群-7月18日上海线下交流会的内容分享(有高清录像视频的链接) 代码自动生成: ...

  5. 服务中没有ASP.net State service 状态服务 (ASP.NET state server)

    Windows7\8 装完后,服务中没有ASP.net状态服务 (ASP.NET state server) 没有找到具体的解决办法,有遇到同样问题的吗? 装IIS就行了,步骤是: 进入控制面板--- ...

  6. Asp.net MVC2.0系列文章-添加操作

    创建数据模型Model 数据模型主要包括数据信息.验证规则以及业务逻辑. 创建Model的方式有多种,可以使用微软的ADO.NET Entity Data Model,也可以使用第三方工具生成实体对象 ...

  7. ABP(现代ASP.NET样板开发框架)系列之2、ABP入门教程

    点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之2.ABP入门教程 ABP是"ASP.NET Boilerplate Project (ASP.NET样 ...

  8. 《ASP.NET Core 高性能系列》致敬伟大的.NET斗士甲骨文

    写在开始 三年前,曾写过一篇文章:从.NET和Java之争谈IT这个行业,当时遭到某些自认为懂得java就了不起的Javaer抨击,现在可以致敬伟大的.NET斗士甲骨文了 (JDK8以上都需要收费,A ...

  9. 基于DDD的现代ASP.NET开发框架--ABP系列之1、ABP总体介绍

    点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之1.ABP总体介绍 ABP是"ASP.NET Boilerplate Project (ASP.NET样 ...

  10. ASP.NET AJAX入门系列(1):概述

    经常关注我的Blog的朋友可能注意到了,在我Blog的左边系列文章中,已经移除了对Atlas学习手记系列文章的推荐,因为随着ASP.NET AJAX 1.0 Beta版的发布,它们已经不再适用,为了不 ...

最新文章

  1. AI一分钟 | ​被大家吐槽的网红机器人索菲亚开微博了;阿里人工智能团队iDST获得道路场景分割三项第一
  2. docker 命令汇总
  3. base64 数据处理
  4. 20160331数据文件offline与open resetlogs2
  5. 配置MGR启动第一个节点时start group_replication一直报ERROR 3092 (HY000):The server is not configured properly
  6. Ubuntu通过可视化界面配置 查找IP地址不存在的解决办法
  7. 美团NLP中心算法实习生招聘
  8. 6 只能在公司代码xxxx的期间2020/08和2020/07中记账
  9. cahrt框架 ios_iOS - Charts(一) - BarChartView
  10. Apache 中 .htaccess 文件设置技巧16则
  11. 洛谷p3392计算机教育新社会,洛谷-P3392 涂国旗
  12. 保护系统 用SVS为Windows穿上“层层”防弹衣
  13. 千图成像python_爬取英雄联盟所有皮肤图片实现千图成像!Python真强!!
  14. 计算机组成和体系结构-Flynn分类法
  15. 3DES加密算法原理
  16. 分类模型confusion matrix混淆矩阵可视化
  17. python模仿微信添加好友截图,一键批量生成微信添加好友聊天截图
  18. 红米AX6000折腾链路聚合
  19. 数字IC秋招手撕代码(二)50%占空比的三分频
  20. 《Linux基础》06. 进程管理 · 服务管理

热门文章

  1. excel内容少却文件很大_Excel文件格式批量转换你会了吗?神操作!Excel文件转XPS格式...
  2. 图论之单源最短路径问题
  3. Jenkins 多服务器自动部署,发布到多台服务器
  4. mysql批量删除指定前缀的表,批量修改表名的SQL语句
  5. 阶段1 语言基础+高级_1-3-Java语言高级_05-异常与多线程_第6节 Lambda表达式_3_编程思想转换体验Lambda的更优写法...
  6. switch and router
  7. 百度地图电子围栏功能的实现
  8. uni-app 引入本地iconfont的正确姿势以及阿里图标引入
  9. python Image 模块处理图片
  10. Linux - Ubuntu Server基础