Session服务器配置指南与使用经验的深入解析
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Session服务器配置指南与使⽤经验的深⼊解析
所有Web程序都会使⽤Session保存数据. 使⽤独⽴的Session服务器可以解决负载均衡场景中的Session共享问题.本⽂介
绍.NET平台下建⽴Session服务器的⼏种办法, 并介绍在使⽤Session时的各种经验和技巧.
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["_SessionId"] != null)
{
string SesssionId = HttpContext.Current.Request.Cookies["_SessionId"].Value.ToString();
SessionCookie = new HttpCookie("_SessionId");
SessionCookie.Value = SesssionId;
} //省略掉中间的代码部分.只保留备份SessionID和找回SessionID的逻辑
//如果cookie总数超过20 个, 重写_SessionId, 以防Session 丢失.
if (HttpContext.Current.Request.Cookies.Count > 20 && SessionCookie != null)
{
if (SessionCookie.Value != string.Empty)
{
HttpContext.Current.Response.Cookies.Remove("_SessionId");
HttpContext.Current.Response.Cookies.Add(SessionCookie);
}
}
return true;
}
将Session保存在独⽴的服务器中可以实现在多台Web服务器之间共享Session.虽然我们也可以⾃⼰开发Session存储系统, 但是使⽤⾃带的存储机制将更加便捷.
Off设置为不使⽤Session功能⽆
InProc设置为将Session存储在进程内,就是ASP中
性能最⾼
的存储⽅式,这是默认值。
StateServer设置为将Session存储在独⽴的状态服务中。
性能损失10-15%
通常是aspnet_state.exe进程.
SQLServer设置将Session存储在SQL Server中。
性能损失10-20%
Customer⾃定制的存储⽅案由实现⽅式确定
我们可以在Web.Config中配置程序使⽤的Session存储⽅式.默认情况下是InProc, 即保存在IIS进程中. 关于Off, InProc和Customer本⽂不做讲解. 相关⽂章⼤家都可以在⽹上搜索到.
下⾯主要讲解 StateServer 和 SQLServer 的应⽤.
1.启动 State service服务.(这个服务默认的状态为⼿动.修改为⾃动并启动.)
2.修改注册表: [HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\aspnet_state\Parameters]
设置 AllowRemoteConnection = 1 , 设置 Port = 42424 (⼗进制,默认即为42424)
Port是服务的端⼝号
AllowRemoteConnection 表⽰是否允许其他机器连接,0为仅能本机使⽤,1为可以供其他机器使⽤.
在Web应⽤程序的Web.Config中, 我们需要修改 <configuration> / <system.web> 的<sessionState>节点.如果没有
没有则添加(默认使⽤的是InProc⽅式)
复制代码代码如下:
<sessionState
mode="StateServer"
stateConnectionString="tcpip=服务器ip:42424"
cookieless="false"
timeout="60"/>
上⾯的参数我们可以根据需要修改.
使⽤SqlServer模式搭建Session服务器端有两种⽅式. 1.0和1.1版本请使⽤⽅式a, 2.0即以上版本请使⽤⽅式b.
在 1.0和1.1 版本中, 只能使⽤这种⽅式.对于2.0及其以上版本,请使⽤aspnet_regsql.exe⼯具.(当然此⽅法也通⽤2.0版本)
.net提供了数据库安装脚本,可以在机器的windows⽂件夹中找到:
C:\WINDOWS\\Framework\v2.0.50727\ InstallSqlState.sql
C:\WINDOWS\\Framework\v2.0.50727\ InstallSqlStateTemplate.sql
根据的版本不同, 需要使⽤不同的SQL脚本. 主要有1.1和2.0两个版本,可以在不同的版本⽂件夹找到这两个SQL.
InstallSqlState.sql 是创建默认名称的数据库"[ASPState]".此SQL可以直接运⾏.
InstallSqlStateTemplate.sql 可以使⽤⾃⼰指定的数据库保存数据.此SQL需要⾃⼰修改后运⾏, 打开SQL⽂件将其中[DatabaseNamePlaceHolder] 替换为⾃⼰指定的数据库名称.
执⾏installsqlstate.sql时不需要指定数据库,可以在任意数据库上执⾏.此SQL会⾃⼰创建新的数据库
2.0版本后微软提供了aspnet_regsql.exe⼯具可以⽅便的配置Session数据库.该⼯具位于 Web 服务器上的"系统根⽬录\\Framework\版本号"⽂件夹中.
使⽤举例:
aspnet_regsql.exe -S . -U sa -P 123456 -ssadd -sstype p
表⽰数据库实例名称. 可以⽤"."表⽰本机.
表⽰⽤户名和密码.
可以再-U –P 与 -E中选择⼀组. –E表⽰以当前系统⽤户通过windows⾝份验证登录数据库, -U -P则是使⽤SqlServer⽤户登录数据库.
-ssadd表⽰是添加Session数据库, -ssremove表⽰移除Session数据库.
将会话数据存储到 SQL Server tempdb 数据库中。
这是默认设置。
如果将会话数据存储到 tempdb 数据
库中,则在重新启动 SQL Server 时将丢失会话数据。
将会话数据存储到 ASPState 数据库中,⽽不是存储到 tempdb 数据库中。
将会话数据存储到⾃定义数据库中。
如果指定选项,则还必须使⽤选项包括⾃定义数据库的名称。
此房是同样需要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.在web farm中,请确认在所有的web服务器上有相同的<machineKey>
2. 要保存在Session中的对象是可序列化的。
3.为了在web farm中的不同web服务器上维护session state,IIS Metabase中的⽹站应⽤程序路径(如\LM\W3SVC\2)应该在
所有的服务器上保持⼀致(⼤⼩写敏感).
4. 处理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"
/>
1. 要保存在Session中的对象是可序列化的。
2. 如果使⽤了默认是数据库, 则在客户端配置⽂件中的数据库链接字符串的⽤户,需要拥有ASPState和tempdb两个库的dbowner权限.
3. 在SQLServer模式下,session过期是由SQL Agent使⽤⼀个注册任务完成的,要确认SQL Agent已经运⾏。
否则⽆法清理过期的Session数据, 会导致数据库数据⼀直增加.
4. 如果使⽤SqlServer模式时, 对于Web场中的各服务器的 应⽤程序路径必须是相同的。
请在 IIS 配置数据库中对Web 场中的所有 Web 服务器进⾏ Web 站点的应⽤程序路径同步。
⼤⼩写⼀定要相同,因为 Web 站点的应⽤程序路径是区分⼤⼩写的。
5.需要让所有机器的MachineKey相同.在Machine.Config中配置:
复制代码代码如下:
<machineKey
validationKey="1234567890123456789012345678901234567890AAAAAAAAAA"
decryptionKey="123456789012345678901234567890123456789012345678"
validation="SHA1"
decryption="Auto"
/>
1. 不能直接通过Session服务器在和ASP之间共享Session. 请使⽤微软提供的解决⽅案:
/zh-cn/library/aa479313.aspx
2. 在不同的应⽤程序或⼀个⽹站的不同虚拟⽬录之间⽆法共享Session
3. Session的过期时间是滑动时间.
4. Session存储.NET⾃带的值类型性能最优. 存储对象会降低性能.
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⽂件没有交给的ISAPI处理, 那么根据服务器速度在每个Frame页⾯⽣成不同的SessionID,再刷新后相同都等于最后⼀个SessionID.
解决办法是将.htm后缀改成.aspx, 或者将.htm⽂件交给的ISAPI处理.
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服务器搭建⼈员有所帮助.。