当前位置: 移动技术网 > IT编程>开发语言>PHP > Session服务器配置指南与使用经验的深入解析

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

2019年04月09日  | 移动技术网IT编程  | 我要评论
一.摘要
所有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服务器搭建人员有所帮助. 

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网