欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

如何解决asp.net负载均衡时Session共享的问题

程序员文章站 2022-04-10 09:59:30
每个客户端在访问网站时,都会创建相应的session,用来保存客户的状态信息,网站如果做了负载均衡,session共享是要做的,iis对于session的存储有五种模式...

每个客户端在访问网站时,都会创建相应的session,用来保存客户的状态信息,网站如果做了负载均衡,session共享是要做的,iis对于session的存储有五种模式

一、asp.net session存储方式

1、inproc模式(进程内模式) 。为默认设置。

会话状态存储在web服务器上的内存中。

2、stateserver模式(状态服务器模式)。

会话状态存储在一个名为asp.net状态服务的单独进程中。这确保了在重新启动web应用程序时会保留会话状态,并让会话状态可用于网路场中的多个web服务器。

3、sql server模式。

会话状态存储到一个sql server数据库中。这确保了在重新启动web应用程序时会保留会话状态,并让会话状态可用于网路场中的多个web服务器。

4、custom模式

此模式允许您指定自定义存储提供程序。

5、off模式

此模式禁止会话状态。

二、使用stateserver存储session

如果网站做了负载均衡,对于session存储就只能选择2、3、4了,下面先来介绍一下stateserver模式,首先得开启状态服务

如何解决asp.net负载均衡时Session共享的问题

然后再对web站点的“会话状态”进行设置

如何解决asp.net负载均衡时Session共享的问题

启用本机的状态服务

如何解决asp.net负载均衡时Session共享的问题

会自动在web.config里生成配置文件(如果不能生成就手动添加)

<sessionstatemode=”stateserver”stateconnectionstring=”tcpip=loopback:42424″timeout=”20″/>

但是这里就存在一个问题,如果每台服务器都照上面配置,各服务器的session都存储在本机的stateserver里面,还是没有启动共享的作用,这里就需要让一台stateserver共享出来让其他服务器访问,并将session存储到上面,运行regedit → 打开注册表 → 找到hkey_local_machine\system\currentcontrolset\services\aspnet_state\parameters节点 → 将 allowremoteconnection 的键值设置成“1”(1 为允许远程电脑的连接,0 代表禁止)

如何解决asp.net负载均衡时Session共享的问题

也可以修改stateserver的端口

如何解决asp.net负载均衡时Session共享的问题

接下来将其它服务器中web.config的配置文件进行修改(sessionstate指向开启了允许远程访问的stateserver)

<sessionstatemode=”stateserver”stateconnectionstring=”tcpip=10.16.5.30:22222″timeout=”20″/>

用stateserver这种共享式的session存储方式不仅有安全隐患,而且像上面那台共享的stateserver只要重启服务器,所有的session都会丢失,所以这种session存储方式不是很完美,用stateserver存储sesssion比较适合单机iis开启多进程的。

如何解决asp.net负载均衡时Session共享的问题

三、使用sql server存储session

要做保证安全并且不会因为重启服务器导致session丢失,那就要用sql server来存储session,asp.net 2.0版本后微软提供了aspnet_regsql.exe工具可以方便的配置session数据库.该工具位于 web 服务器上的系统根目录microsoft.netframework版本号文件夹中

cd c:\windows\microsoft.net\framework64\v4.0.30319
aspnet_regsql.exe -ssadd -sstype c -d <database name> -s <sql server ip> -u <user name> -p <password>
aspnet_regsql.exe -ssadd -sstype c -d aspstate -s 10.16.5.36 -u sa -p haha789

注:<database name>为数据库名为aspstate ,<sql server ip>为数据库实例名像 ibm-pc\sqlexpress (若数据库不是2005的不要写ip地址,否则会连接失败),<user name>为sa(或与sa同等权限的),<password> 为 sa用户名的密码会话定义成功,但是会提示在web应用中进行相应的配置,此时查看sqlserver会发现增加了数据库aspstate,但是没有表。

在命令行下运行如下命令:aspnet_regsql.exe -ssadd -sstype p -s <sql server ip> -u <user name> -p <password>

aspnet_regsql.exe-ssadd-sstypep-s10.16.5.36-usa-phaha789

如何解决asp.net负载均衡时Session共享的问题

该命令对此应用进行了持久化操作。这时会看到aspstate数据库里面多了两张表,aspstatetempsession就可以用来保存session,接下来要对web站点的“会话状态”进行设置

如何解决asp.net负载均衡时Session共享的问题

aspstatetempsessions 表中的sessionid ,包括两个部分:网站生成的24位sessionid及8位appid组成,对于不同的站点,其appid和appname也不同,在能够在不同站点下session共享,就得保证这个32位的sessionid 一致,所以可以通过修改存储过程tempgetappid,使其得到的sessionid与appname无关,修改tempgetappid如下

如何解决asp.net负载均衡时Session共享的问题

修改web.config(在数据库中为aspstate单独分配一个帐户)

<sessionstatemode="sqlserver"sqlconnectionstring="datasource=10.16.5.36;userid=sa;password=haha789"cookieless="false"timeout="20"></sessionstate>

这样就实现了sql server对session的存储,当然也可以用memcache来存储session

四、asp.net错误,验证视图状态mac失败

但在在网站登录访问时却报错了“asp.net错误,验证视图状态mac失败”,baidu了一下,大部分人都说是在页里或web.config里加enableeventvalidation="false" enableviewstatemac="false" viewstateencryptionmode="never" 这些属性的设置。但是这并不从根本上解决问题,相反这样做了反而更加不安全。不能说出错就不用了?出错得解决问题,得从根本上解决问题。

分析错误原因:

asp.net 中有很多涉及到加密的东西,比如 viewstate,比如 formsauthenticationticket,这些东西都是要传送到客户端的,加密才能保障其安全性。加密就得有个私钥,但这个私钥我们并没有指定啊,那是因为 asp.net 自动生成的。但是如果是在网络场或群集中,或者在某些做了 cdn 加载的虚拟主机中,由于涉及到多台服务器 asp.net 就无法为各台机器自动生成相同的私钥,这就造成了这个服务器产生的数据,那台服务器解析不出来。于是就出错了。怎么办?既然 asp.net 在多台服务器上无法自动随机生成相同的私钥,那只有我们自己指定了。

machinekey生成工具,自动生成代码

将生成的machinekey插入到web.config中:

<view class="list" wx:for="{{list}}" wx:key>
 <view class="item">
  <view class="wrap">{{item}}</view>
  <view class="delete"><text>删除</text></view>
 </view>
</view>

machinekey的作用:

asp.net 使用 forms authentication 时的 cookie 数据的加密和解密。以确保这部分数据不会被篡改viewstate 数据的加密和解密。以确保这部分数据不会被篡改。使用进程外session(out-of-process session)时,对会话状态标识进行验证。利用sessionstatemode的sqlserver来实现session共享,毕竟是微软的东西,具有一定的局限行,只能是sql server。其实session共享可以用其他的数据库,比如memcache、redis

五、asp.net 状态数据库faq

1、如果把session值存放到数据库中去,用户关闭了程序那怎么样清空数据库里的session值呢?

实际asp.net在创建状态数据库的时候会在sql server代理(sql server agent)的作业中添加一个作业,名称为<状态数据库名>_job_deleteexpiredsessions。如果打开sql server代理服务数据库可以通过添加的状态记录的超时时间字段(exprires)定期对超时的状态数据进行删除。

如何解决asp.net负载均衡时Session共享的问题

2、aspstatetempsessions表中的sessionid字段如何使用?

数据库中此表的sessionid字段的值,由sessionid和appid共同组成,最后8位为appid所以,后8位之前一定是sessionid。例如,存储在数据库中的值为"ekr30c3mwvnc3145yrswew3a037e5e5a",后8位的"037e5e5a"为appid,而前面的"ekr30c3mwvnc3145yrswew3a"为应用程序中你可以使用session.sessionid获得的字符串。

如何解决asp.net负载均衡时Session共享的问题

3、如何判断session何时被更新的?

session记录被更新时会同时更新expires和lockdatelocal,expires字段为utc时间,如果想通过本地之间进行比较判断还是需要使用lockdatelocal。

4、获得web.config配置文件节点信息的程序?

''获得web.config文件配置实例

dim configuration as system.configuration.configuration = system.web.configuration.webconfigurationmanager.openwebconfiguration("~/web.config")

''获得状态配置节点实例

dim msessionstatesection as system.web.configuration.sessionstatesection = ctype(configuration.getsection("system.web/sessionstate"),system.web.configuration.sessionstatesection)

''获得状态模式

response.write(msessionstatesection.mode)

''获得状态超时时间

response.write(msessionstatesection.timeout)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。