Session服务器配置指南与使用经验的深入解析

一.摘要
所有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服务器搭建人员有所帮助.

(0)

相关推荐

  • IIS服务器中 ASP.NET State Service 开启后 Session 仍容易丢失的问题终极解决办法

    解决方法一: 1. 开启ASP.NET State Service服务: 选择管理工具->服务,找到ASP.NET State Service,点开后选择启动,并将启动类型设为自动. 2. 设置程序配置文件: 将web.config打开,会看到有一行是<sessionState mode="InProc" stateConnectionString="tcpip=127.0.0.1:42424" timeout="20"/>,如

  • 用PHP实现多服务器共享SESSION数据的方法

    PHP 实现多服务器共享 SESSION 数据 /google 的广告条--> 一.问题起源 稍大一些的网站,通常都会有好几个服务器,每个服务器运行着不同功能的模块,使用不同的二级域名,而一个整体性强的网站,用户系统是统一的,即一套用户名.密码在整个网站的各个模块中都是可以登录使用的.各个服务器共享用户数据是比较容易实现的,只需要在后端放个数据库服务器,各个服务器通过统一接口对用户数据进行访问即可.但还存在一个问题,就是用户在这个服务器登录之后,进入另一个服务器的别的模块时,仍然需要重新登录,这

  • 多php服务器实现多session并发运行

    首先介绍一下session的概念: 所谓session是微软首先提出的,在asp中最先集成.由于session的采用,大大方便了web开发员的工作.一时间asp风靡全球.现在php4也加入session的支持,再度显示出open source 的强大力量.和Cookie类似,设计Session的目的也是为了在一个访问期间在不同的页面间传输数据以解决http协议无状态的问题,但Session更加简单.更加安全.Session 中文没有一个统一的译法,我习惯上译为会话.关于session的意义大家都

  • asp.net页面状态管理cookie和服务器状态管理Session

    Cookie:是存储在客户端文件系统的文本文件中或客户端浏览器对话的客户端浏览器对话的内存中的少量的数据.当我们在访问一个网站网页,当用户请求该网页时,应用程序会首先检查用户在此前是否已经登录过,我们可以通过读取Cookie获取用户信息来判断是否让它继续访问 记录Cookie信息 创建一个名称是user的Cookie对象:HttpCookie cookie=new HttpCookie("user"); 给Cookie赋值,只能使用字符串赋值:cookie.Value="ch

  • PHP实现多服务器session共享之NFS共享的方法

    PHP实现多服务器session共享之NFS共享  前言,Nio大侠提出了session多服务器共享的问题,原文请见PHP 实现多服务器共享 SESSION 数据. 其中,有一种方法就是利用NFS来共享session,如果session量比较大并且所有的session文件都在同一个子目录下的话,那么可能会由此带来很严重的负载问题,甚至导致网站无法使用.本文就是对这个方案做一下详细的解说. 首先,修改 php.ini的 session.save_path 选项,大致如下: session.save

  • 深入Memcache的Session数据的多服务器共享详解

    一相关介绍1.memcache + memcache的多服务器数据共享的介绍,请参见http://www.guigui8.com/index.php/archives/206.html2.session机制:session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息.当程序需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否已包含了一个session标识- 称为sessionid,如果已包含一个sessionid

  • PHP 实现多服务器共享 SESSION 数据

    一.问题起源 稍大一些的网站,通常都会有好几个服务器,每个服务器运行着不同功能的模块,使用不同的二级域名,而一个整体性强的网站,用户系统是统一的,即一套用户名.密码在整个网站的各个模块中都是可以登录使用的.各个服务器共享用户数据是比较容易实现的,只需要在后端放个数据库服务器,各个服务器通过统一接口对用户数据进行访问即可.但还存在一个问题,就是用户在这个服务器登录之后,进入另一个服务器的别的模块时,仍然需要重新登录,这就是一次登录,全部通行的问题,映射到技术上,其实就是各个服务器之间如何实现共享

  • Session服务器配置指南与使用经验的深入解析

    一.摘要所有Web程序都会使用Session保存数据. 使用独立的Session服务器可以解决负载均衡场景中的Session共享问题.本文介绍.NET平台下建立Session服务器的几种办法, 并介绍在使用Session时的各种经验和技巧. 二.关于Session,SessionID和CookiesSession数据保存在服务器端, 但是每一个客户端都需要保存一个SessionID, SessionID保存在Cookies中, 关闭浏览器时过期. 在向服务器发送的HTTP请求中会包含Sessio

  • Windows Server 2016 服务器配置指南之PHP7运行环境搭建方法

    因为 PHP7 在 Windows 已经提供了完整的 64bit 支持,所以选择 64bit 系统安装 64bit PHP7 将获得更好的性能表现. PHP7 需要 VC14 ( Visual C++ Redistributable for Visual Studio 2015 x86 or x64)做运行库,所以我们先要安装 VC14. 一.下载并安装运行库: x64 安装 64 位的运行库,x86 安装 32位的运行库. 32位下载:https://download.microsoft.co

  • hibernate通过session实现增删改查操作实例解析

    今天学习了一下如何通过hibernate来实现对数据库的增删改查,下面来简单介绍一下: 首先创建个Student类: package com.hibernate.model; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.T

  • spring session同域下单点登录实现解析

    Session会话管理 在Web项目开发中,Session会话管理是一个很重要的部分,用于存储与记录用户的状态或相关的数据:通常情况下session交由容器(tomcat)来负责存储和管理,但是如果项目部署在多台tomcat中,则session管理存在很大的问题: 1.多台tomcat之间无法共享session,比如用户在tomcat A服务器上已经登录了,但当负载均衡跳转到tomcat B时,由于tomcat B服务器并没有用户的登录信息,session就失效了,用户就退出了登录: 2.一旦t

  • Spring session实现共享单点登录案例过程解析

    一.项目构建 1.案例说明 本文主要演示单点登录功能,会贴出主要配置和代码以及必要解释,全部代码请参考git地址.session共享一个基本原则是将session存储在某个地方,所有的应用都可以访问,这里使用redis存储session.当应用需要认证时,先从redis读取用户信息. 2.基本配置 1)pom.xml <dependency> <groupId>org.springframework.session</groupId> <artifactId>

  • Windows Server 2016 服务器配置指南 之 MariaDB数据库环境搭建方法

    MariaDB 完全兼容 Mysql,并且提供更佳优秀的性能表现.并且 MariaDB 是由开源社区维护,采用 GPl 协议,在去 IOE 化盛行的当下,用 MariaDB 代替 Mysql 是大势所趋! 目前 MariaDB 10.1 拥有 Mysql 5.7 的新特性,MariaDB 10.0 拥有 Mysql 5.6 的新特性,MariaDB 5.5 对应 Mysql 5.5 ,大致如此. 如果你的 VPS 的磁盘基于 SSD,那么使用 MariaDB 10.1 将获得更好的性能表现. 注

  • Windows Server 2016 服务器配置指南之IIS10安装方法

    一.打开 开始菜单 -- 服务器管理器 -- 管理 -- 添加角色和功能 二.选择基于角色或基于功能的安装,单击"下一步" 三.选择从服务器池中选择服务器,单击"下一步" 五.为了保障兼容性,选择性安装 .Net 3.5 兼容旧程序. 六.单击 "下一步" 七.开始安装和安装结束 八.然后我们就可以在开始菜单中找到 IIS 了,建议设置 固定到"开始"屏幕 ,方面之后的操作 九.扁平化的系统中,IIS 设置依旧原汁原味啊- 十

  • hibernate关于session的关闭实例解析

    本文研究的主要是hibernate关于session的关闭,具体如下. Student student = new Student(); student.setName("Jan"); student.setAge("22"); student.setAddress("广东省肇庆市"); Session session =HibernateUtil.getSessionFactory().getCurrentSession(); session.

  • Hibernate单表操作实例解析

    单一主键 assigned:由Java应用程序负责生成(即手工的赋值) native:由底层的数据库自动的生成标示符,如果是MySQL就是auto_increment,如果是Oracle就是sequence,等等 操作的时候还是需要结合hibernate.cfg.xml文件的,因为数据库中的hbm2ddl.auto属性如果是update的时候,设置为主键自增是可以的:但是如果是create的时候,第二次如果不手工的改变,恐怕就要出BUG了. 基本类型 一般来说,按照Java的数据类型进行操作就可

  • Hibernate中获取Session的两种方式代码示例

    Session:是应用程序与数据库之间的一个会话,是Hibernate运作的中心,持久层操作的基础.对象的生命周期/事务的管理/数据库的存取都与Session息息相关. Session对象是通过SessionFactory构建的,下面举个例子来介绍Hibernate两种获取session的方式. 日志,是编程中很常见的一个关注点.用户在对数据库进行操作的过程需要将这一系列操作记录,以便跟踪数据库的动态.那么一个用户在向数据库插入一条记录的时候,就要向日志文件中记录一条记录,用户的一系列操作都要在

随机推荐