本文转自:http://www.cnblogs.com/zhangziqiu/archive/2009/03/26/SessionServer.html

一.摘要

所有Web程序都会使用Session保存数据. 使用独立的Session服务器可以解决负载均衡场景中的Session共享问题.本文介绍.NET平台下建立Session服务器的几种办法, 并介绍在使用Session时的各种经验和技巧.

二.关于Session,SessionID和Cookies

Session数据保存在服务器端, 但是每一个客户端都需要保存一个SessionID, SessionID保存在Cookies中, 关闭浏览器时过期.

在向服务器发送的HTTP请求中会包含SessionID, 服务器端根据SessionID获取获取此用户的Session信息.

很多初级开发人员不知道SessionID和Cookies的关系, 所以常常认为两者没有联系. 这是不正确的. 正是因为SessionID保存在Cookies中, 所以在我们保存Cookies的时候,一定要注意不要因为Cookies的大小和个数问题而导致SessionID对象. 在我们的程序中, 对SessionID的Cookies有特殊的处理:

        /// <summary>
/// 写入cookie.
/// </summary>
/// <param name="day"></param>
/// <returns></returns>
public bool SetCookie(int day)
{
string CookieName = GetType().ToString();
HttpCookie SessionCookie = null; //对 SessionId 进行备份.
if (HttpContext.Current.Request.Cookies["ASP.NET_SessionId"] != null)
{
string SesssionId = HttpContext.Current.Request.Cookies["ASP.NET_SessionId"].Value.ToString();
SessionCookie = new HttpCookie("ASP.NET_SessionId");
SessionCookie.Value = SesssionId; }
            //省略掉中间的代码部分.只保留备份SessionID和找回SessionID的逻辑

            //如果cookie总数超过20 个, 重写ASP.NET_SessionId, 以防Session 丢失.
if (HttpContext.Current.Request.Cookies.Count > 20 && SessionCookie != null)
{
if (SessionCookie.Value != string.Empty)
{
HttpContext.Current.Response.Cookies.Remove("ASP.NET_SessionId");
HttpContext.Current.Response.Cookies.Add(SessionCookie);
}
} return true;
}

三.搭建Session服务器的几种方式

将Session保存在独立的服务器中可以实现在多台Web服务器之间共享Session.虽然我们也可以自己开发Session存储系统, 但是使用ASP.NET自带的存储机制将更加便捷.

.NET提供了5种保存Seission的方式:

方式名称

存储方式 性能

Off

设置为不使用Session功能

InProc

设置为将Session存储在进程内,就是ASP中的存储方式,这是默认值。

性能最高

StateServer

设置为将Session存储在独立的状态服务中。通常是aspnet_state.exe进程.

性能损失10-15%

SQLServer

设置将Session存储在SQL Server中。

性能损失10-20%

Customer

自定制的存储方案

由实现方式确定

我们可以在Web.Config中配置程序使用的Session存储方式.默认情况下是InProc, 即保存在IIS进程中. 关于Off, InProc和Customer本文不做讲解. 相关文章大家都可以在网上搜索到.

下面主要讲解 StateServer 和 SQLServer 的应用.

四.使用 StateServer 模式搭建Session服务器

(1)服务器端配置

1.启动 Asp.net State service服务.(这个服务默认的状态为手动.修改为自动并启动.)

2.修改注册表: [HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\aspnet_state\Parameters]

设置 AllowRemoteConnection = 1 , 设置 Port = 42424 (十进制,默认即为42424)

Port是服务的端口号

AllowRemoteConnection 表示是否允许其他机器连接,0为仅能本机使用,1为可以供其他机器使用.

(2)客户端设置

在Web应用程序的Web.Config中, 我们需要修改 <configuration> / <system.web> 的<sessionState>节点.如果没有

没有则添加(默认使用的是InProc方式)

<sessionState
mode="StateServer"
stateConnectionString="tcpip=服务器ip:42424"
cookieless="false"
timeout="60"/>

上面的参数我们可以根据需要修改.

五.使用SqlServer模式搭建Session服务器

(1)服务器端配置

使用SqlServer模式搭建Session服务器端有两种方式. ASP.NET 1.0和1.1版本请使用方式a, 2.0即以上版本请使用方式b.

a.使用SQL文件创建Session数据库

在ASP.NET 1.0和1.1 版本中, 只能使用这种方式.对于2.0及其以上版本,请使用aspnet_regsql.exe工具.(当然此方法也通用2.0版本)

.net提供了数据库安装脚本,可以在机器的windows文件夹中找到:

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\ InstallSqlState.sql

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\ InstallSqlStateTemplate.sql

根据ASP.NET的版本不同, 需要使用不同的SQL脚本. ASP.NET主要有1.1和2.0两个版本,可以在不同的版本文件夹找到这两个SQL.

InstallSqlState.sql 是创建默认名称的数据库"[ASPState]".此SQL可以直接运行.

InstallSqlStateTemplate.sql 可以使用自己指定的数据库保存数据.此SQL需要自己修改后运行, 打开SQL文件将其中 [DatabaseNamePlaceHolder] 替换为自己指定的数据库名称.

执行installsqlstate.sql时不需要指定数据库,可以在任意数据库上执行.此SQL会自己创建新的数据库

b. 使用aspnet_regsql.exe工具

ASP.NET 2.0版本后微软提供了aspnet_regsql.exe工具可以方便的配置Session数据库.该工具位于 Web 服务器上的"系统根目录\Microsoft.NET\Framework\版本号"文件夹中.

使用举例:

aspnet_regsql.exe -S . -U sa -P 123456 -ssadd -sstype p

  

-S参数:

表示数据库实例名称. 可以用"."表示本机.

-U和-P参数:

表示用户名和密码.

-E参数:

可以再-U –P 与 -E中选择一组. –E表示以当前系统用户通过windows身份验证登录数据库, -U -P则是使用SqlServer用户登录数据库.

-ssadd / –ssremove 参数:

-ssadd表示是添加Session数据库, -ssremove表示移除Session数据库.

sstype 参数:

选项

说明

t

将会话数据存储到 SQL Server tempdb 数据库中。这是默认设置。如果将会话数据存储到 tempdb 数据库中,则在重新启动 SQL Server 时将丢失会话数据。

p

将会话数据存储到 ASPState 数据库中,而不是存储到 tempdb 数据库中。

c

将会话数据存储到自定义数据库中。如果指定 c 选项,则还必须使用 -d 选项包括自定义数据库的名称。

(2)Session客户端设置

此房是同样需要Web应用程序修改Web.Config中的<sessionState>节点.如果使用默认的数据库(ASPState库), 则配置如下:

    <sessionState
mode="SQLServer"
sqlConnectionString="server=192.168.9.151; uid=sa; pwd=123456;"
/>

如果使用了自定义的数据库名称,则还需要制定allowCustomSqlDatabase属性并在数据库连接串中指定数据库:

    <sessionState
mode="SQLServer"
allowCustomSqlDatabase="true"
sqlConnectionString="server=192.168.9.151; DataBase=MyAspState;uid=sa; pwd=123456;"
/>

六.使用经验与技巧总结

下面是SessionID, Session_End时间, StatServer模式 和 SqlServer模式的各种经验和技巧总结.

(1)StateServer模式:

1.在web farm中,请确认在所有的web服务器上有相同的<machineKey>

2. 要保存在Session中的对象是可序列化的。

3.为了在web farm中的不同web服务器上维护session state,IIS Metabase中的网站应用程序路径(如\LM\W3SVC\2)应该在所有的服务器上保持一致(大小写敏感).

4. ASP.NET处理Session是在Machine.Config中配置的HttpModuel模块, 在.NET的安装目录下的Config文件夹中, 查看Web.Config(1.1版本是在Machine.Config):

        <httpModules>
...
            <add name="Session" type="System.Web.SessionState.SessionStateModule"/>
...
        </httpModules>

确认此模块是否存在.

5.StateServer不支持负载均衡, 所以如果大并发推荐使用SqlServer模式, 可以享受到SqlServer的高性能和安全性.虽然存储效率会有下降.

6.需要让所有机器的MachineKey相同.在Machine.Config中配置:

<machineKey
validationKey="1234567890123456789012345678901234567890AAAAAAAAAA"
decryptionKey="123456789012345678901234567890123456789012345678"
validation="SHA1"
decryption="Auto"
/>

(2)SqlServer模式:

1. 要保存在Session中的对象是可序列化的。

2. 如果使用了默认是数据库, 则在客户端配置文件中的数据库链接字符串的用户,需要拥有ASPState和tempdb两个库的dbowner权限.

3. 在SQLServer模式下,session过期是由SQL Agent使用一个注册任务完成的,要确认SQL Agent已经运行。否则无法清理过期的Session数据, 会导致数据库数据一直增加.

4. 如果使用SqlServer模式时, 对于Web场中的各服务器的 ASP.NET 应用程序路径必须是相同的。请在 IIS 配置数据库中对 Web 场中的所有 Web 服务器进行 Web 站点的应用程序路径同步。大小写一定要相同,因为 Web 站点的应用程序路径是区分大小写的。

5.需要让所有机器的MachineKey相同.在Machine.Config中配置:

<machineKey
validationKey="1234567890123456789012345678901234567890AAAAAAAAAA"
decryptionKey="123456789012345678901234567890123456789012345678"
validation="SHA1"
decryption="Auto"
/>

(3)Session:

1. 不能直接通过Session服务器在ASP.NET和ASP之间共享Session. 请使用微软提供的解决方案:    http://msdn.microsoft.com/zh-cn/library/aa479313.aspx

2. 在不同的应用程序或一个网站的不同虚拟目录之间无法共享Session

3. Session的过期时间是滑动时间.

4. Session存储.NET自带的值类型性能最优. 存储对象会降低性能.

(4)SessionID:

1.SessionID 还可以保存在URL上, 设置Web.Config文件中的System.Web/sessionState节点的Cookiesless属性即可:

    <sessionState
cookieless="UseUri"
/>
 

2. 一般在Session超时或删除之后,SessionID保持不变. 因为Session过期后会在服务器端清除数据, 但是SessionID保存在用户浏览器上, 所以只要浏览器不关闭则HTTP头中的SessionID保持不变.

3.关闭浏览器后再访问, SessionID会不同.

4.每打开一个IE6窗口, SessionID都不同, 在IE6中两个窗口的Session不能共享.

5.FireFox的标签页和新的FireFox窗口, SessionID都相同, 在FF的窗口和标签页上Session能共享.

6.对于包含FrameSet的页面,比如:

<frameset cols="25%,50%,25%">
<frame src="SessionID.aspx">
<frame src="SessionID.aspx">
<frame src="SessionID.aspx">
</frameset>

如果后缀名是.htm并且.htm文件没有交给ASP.NET的ISAPI处理, 那么根据服务器速度在每个Frame页面生成不同的SessionID, 再刷新后相同都等于最后一个SessionID.

解决办法是将.htm后缀改成.aspx, 或者将.htm文件交给ASP.NET的ISAPI处理.

(5)Session_End事件:

1. Session_End仅在InProc模式中可用

2. 关闭浏览器,Session_End是不会触发的。HTTP是一种无状态协议,服务器没有办法知道你的浏览器是否已经关闭。

3. 当Session因为时间过期或调用Session.Abandon时,Session_End才会触发.Session.Clear()仅仅是清除数据,但没有删除session。

4. Session_End由一个后台线程触发,使用工作者进程账号运行. 所以程序不会通知发生的错误.

5. 在Session_End访问数据库要考虑权限问题. Session_End是用运行工作者进程(aspnet_wp.exe)的帐号运行的,这个账号可以在machine.config中指定。因此,在Session_End中,如果使用integrity security连接SQL,它将使用工作者进程账号身份连接,这可能会引起登录失败.

6.因为Session_End是有独立线程出发的, 所以在Session_End中无法使用HttpContext对象(Request,Response,Server等对象都在HttpContext中),  即无法使用 Response.Redirect 和Server.Transfer等方法.

七.总结

我已经使用SqlServer模式对公司的多台服务器实现了Session共享, 服务器重启也不会导致用户预定过程重新开始(预定过程需要的Session不会丢失).  希望本文对具体的Session服务器搭建人员有所帮助.

参考文献:

使用一个 SQL 数据库 SQL Server 会话状态的所有应用程序可能导致瓶颈

http://support.microsoft.com/kb/836680/zh-cn

ASP.NET 中 Session 实现原理浅析 [1] /[2]

http://www.cnblogs.com/flier/archive/2004/08/04/30226.html

http://www.cnblogs.com/flier/archive/2004/08/07/30902.html

理解Session State模式+ASP.NET SESSION丢失FAQ [翻译]

http://www.cnblogs.com/tonyqus/archive/2006/10/24/522618.html

作者:张子秋 出处:http://www.cnblogs.com/zhangziqiu/ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

[转]Session服务器配置指南与使用经验的更多相关文章

  1. Session服务器配置指南与使用经验

    一.摘要 所有Web程序都会使用Session保存数据. 使用独立的Session服务器可以解决负载均衡场景中的Session共享问题.本文介绍.NET平台下建立Session服务器的几种办法, 并介 ...

  2. 苹果ATS特性服务器配置指南 HTTPS 安卓可以用 IOS 报错。

    解决方案:https://www.qcloud.com/document/product/400/6973 ATS检测:https://www.qcloud.com/product/ssl#userD ...

  3. 关于搭建Session服务器(转载)

    Session服务器配置指南与使用经验 一.摘要 所有Web程序都会使用Session保存数据. 使用独立的Session服务器可以解决负载均衡场景中的Session共享问题.本文介绍.NET平台下建 ...

  4. DotNet基础

    DotNet基础 URL特殊字符转义 摘要: URL中一些字符的特殊含义,基本编码规则如下: 1.空格换成加号(+) 2.正斜杠(/)分隔目录和子目录 3.问号(?)分隔URL和查询 4.百分号(%) ...

  5. P6 EPPM 安装与配置指南 16 R1 2016.4

       关于安装和 配置P6 EPPM 本指南告诉你如何自动 安装和配置您的应用程序. 在您开始之前,阅读 先决条件 P6 EPPM配置 (7页). 安装P6 EPPM 您将使用 安装程序 (窗口) . ...

  6. 通过Spring Session实现新一代的Session管理

    长期以来,session管理就是企业级Java中的一部分,以致于我们潜意识就认为它是已经解决的问题,在最近的记忆中,我们没有看到这个领域有很大的革新. 但是,现代的趋势是微服务以及可水平扩展的原生云应 ...

  7. 转:通过Spring Session实现新一代的Session管理

    长期以来,session管理就是企业级Java中的一部分,以致于我们潜意识就认为它是已经解决的问题,在最近的记忆中,我们没有看到这个领域有很大的革新. 但是,现代的趋势是微服务以及可水平扩展的原生云应 ...

  8. [知识库分享系列] 二、.NET(ASP.NET)

    最近时间又有了新的想法,当我用新的眼光在整理一些很老的知识库时,发现很多东西都已经过时,或者是很基础很零碎的知识点.如果分享出去大家不看倒好,更担心的是会误人子弟,但为了保证此系列的完整,还是选择分享 ...

  9. Windows Server 2008 R2 添加且制成“NFS服务器”角色后与Unix客户端匿名访问常见问题

    在复杂的主机与网络环境中,我们可能会接触到多种主机与操作系统,配合Windows Server 2008 R2的原生“NFS服务器”功能可以让这样的复杂操作系统更方便应用. 然而面对网络上众多的帮助指 ...

随机推荐

  1. codeforces A. New Year Candles 解题报告

    题目链接:http://codeforces.com/problemset/problem/379/A 题目意思:给定a支蜡烛(每支蜡烛可以燃烧1小时),可以在燃尽的a支蜡烛中看能组成多少组b支蜡烛, ...

  2. Excel VBA Dir

    内容来自ExcelHome网站 一.题目: 要求编写一段代码,运用Dir函数返回一个文件夹的文件列表.二.代码:Sub 示例_1_12()        Dim wjm        wjm = Di ...

  3. Windows环境下配置Vim为Python的IDE

    (一)安装Python 2.7 在官网下载Python,并安装,我的安装路径是D:\Program Files\Python.安装完成后编辑环境变量Path,在其后添加;D:\Program File ...

  4. linux tricks 之数据对齐。

    转载:http://blog.chinaunix.net/uid-20608849-id-3027953.html   内核为了保持最大的兼容性和代码灵活性,不可能直接对某个数据类型定义它的大小范围. ...

  5. RTP与RTCP协议介绍

    转自:http://zhangjunhd.blog.51cto.com/113473/25481/ 本文主要介绍RTP与RTCP协议. author: ZJ   06-11-17 Blog: [url ...

  6. HTML <img> 标签的 height 和 width 属性

    定义和用法 <img> 标签的 height 和 width 属性设置图像的尺寸. 提示:为图像指定 height 和 width 属性是一个好习惯.如果设置了这些属性,就可以在页面加载时 ...

  7. C++ Primer与c++编程思想的比较(转)

    C++primer是最经典的c++教材之一,它的经典程度要超过thinking in c++.连thinking in c++作者本人都说他写这本书在某种程度上是让读者更好的理解C++primer.但 ...

  8. 小甲鱼PE详解之输入表(导入表)详解(PE详解07)

    捷径并不是把弯路改直了,而是帮你把岔道堵上! 走得弯路跟成长的速度是成正比的!不要害怕走上弯路,弯路会让你懂得更多,最终还是会在终点交汇! 岔路会将你引入万劫不复的深渊,并越走越深…… 在开始讲解输入 ...

  9. 移动端Web开发之我见

    Web比App简单? 前两天有人问手机上做网页简单还是做app简单,我真答不上来.很多人会不以为意的说当然是网页简单,但真的是这样吗? 放眼现在上线的手机网页,大多数都是平时pc的技术沿用过来的,鲜有 ...

  10. 如何查找MySQL中查询慢的SQL语句

    如何查找MySQL中查询慢的SQL语句 更多 如何在mysql查找效率慢的SQL语句呢?这可能是困然很多人的一个问题,MySQL通过慢查询日志定位那些执行效率较低的SQL 语句,用--log-slow ...