跨Web应用程序共享SQL Server会话状态

lha*_*han 10 sql-server asp.net session-variables session-state iis-7.5

我正在设置SQL Server会话状态的一个非常基本的演示,但在使其工作时遇到一些麻烦.我正在尝试使用IIS 7.5和SQL Server 2008 R2在本地运行Windows 7进行测试.

最终,我需要一种方法来跟踪登录到几个不同Web服务器之间负载平衡的系统的用户数量.因此,每次用户登录或注销时,我都需要更新会话变量(存储在SQL中).因此会话ID可能总是不同的.这可能吗?

这是我到目前为止所做的:

  1. 在IIS中创建了两个新站点(Site1和Site2)
  2. 在VS 2010中创建了两个新的Web应用程序项目(Site1和Site2)
  3. 在这两个站点中,在Default.aspx页面上,我创建了一个按钮,单击该按钮时会将"Site1"或"Site2"(取决于站点)保存到名为"LastSiteUsed"的会话变量中.还有另一个按钮,单击该按钮时,将从"LastSiteUsed"会话变量中读取值并将其显示在标签中.
  4. 在SQL中,我创建了一个名为dbSessionTest的新数据库.然后我按照MSDN上的说明使用aspnet_regsql工具安装会话状态数据库.
  5. 在我的两个Web应用程序的Web.config文件中,我添加了以下内容<System.Web>:

<sessionState mode="SQLServer" sqlConnectionString="server=.\sqlexpress;database=dbSessionTest;uid=myUsername;pwd=myPassword" cookieless="false" timeout="20" allowCustomSqlDatabase="true"/>

两个站点都正常运行,但它们似乎没有共享会话.例如,当我单击我的按钮从Site1保存我的会话变量时,我希望能够从Site2读取该值,但它不起作用.Site2只返回"Site2",Site1只返回"Site1".

有没有人对我可能做错了什么有任何想法?我错误地认为我应该能够从Site2读取Site1设置的值吗?

更新:

我可以看到会话数据存储在ASPStateTempSessionsSQL Management Studio 的表中,但每个站点仍然只能看到它编写的值.两个站点都设置会话变量,如下所示:

Session("LastSiteUsed") = "Site2"
Run Code Online (Sandbox Code Playgroud)

这两个网站都在检索如下值:

lblValue.Text = "Value from Session: " & Session("LastSiteUsed").ToString
Run Code Online (Sandbox Code Playgroud)

我是否需要以不同方式访问存储在SQL Server中的会话变量?

更新2:

我已经尝试使用默认数据库ASPState,它是通过运行此命令创建的:

aspnet_regsql.exe -S MyServerName -E -ssadd -sstype p
Run Code Online (Sandbox Code Playgroud)

然后简化我的每个Web.config文件,如:

<sessionState mode="SQLServer" sqlConnectionString="Data Source=.\sqlexpress;User ID=myUsername;Password=myPassword" cookieless="false" timeout="20"/>
Run Code Online (Sandbox Code Playgroud)

但同样,没有运气.我希望能够从Site1设置会话变量,然后从Site2读取值,但它不起作用.再一次,我能够看到ASPStateTempSessions表格中显示的条目,所以我知道它们输入正确.我注意到的一件事是他们有不同的会话ID?

有什么我需要做的不同,以确保在设置/读取相同的会话变量时我的网站之间使用相同的会话ID?

更新3:

我按照本文中的说明修改了SP并添加了一个用于分组的ASPStateTempApplications列.这种方式有效,但前提是我的两个站点都在同一个浏览器中打开(使用标签).我需要能够在IE中打开Site1,将值保存到我的会话变量,关闭浏览器,在Chrome中打开Site2,然后读取值.从我用SQL Server会话状态读取的所有内容......这应该是可能的.

更新4 - 解决方案:

我按照@SilverNinja提供的这篇文章的答案.我ASPState通过命令提示符重新创建数据库(在Update#3中撤消我的SP更改),然后TempGetAppID根据链接的答案修改SP.我还更新了我的两个Web.config文件,以匹配该文章的答案:

<sessionState mode="SQLServer"
              sqlConnectionString="Data Source=.\sqlexpress;User ID=myUsername;Password=myPassword;Application Name=CacheTest"/>
Run Code Online (Sandbox Code Playgroud)

我还在两个Web.config文件中包含了相同的机器密钥:

<machineKey validationKey="59C42C5AB0988049AB0555E3F2128061AE9B75E3A522F25B34A21A46B51F188A5C0C1C74F918DFB44C33406B6E874A54167DFA06AC3BE1C3FEE8506E710015DB" decryptionKey="3C98C7E33D6BC8A8C4B7D966F42F2818D33AAB84A81C594AF8F4A533ADB23B97" validation="SHA1" decryption="AES" />
Run Code Online (Sandbox Code Playgroud)

现在我能够(使用IE)打开我的两个站点,从Site1设置一个值,然后从Site2读取它(反之亦然).当我检查表时,只存在一个SessionID(两个站点正确使用相同的会话).在打开新浏览器(例如,使用Chrome)之前我的想法是错误的,会使用相同的会话 - 新的浏览器将启动它自己的会话.但是,在负载均衡的情况下,这不应该导致任何问题.

Sli*_*SFT 7

您遇到的问题是跨ASP.NET应用程序共享会话状态.SQL Server会话提供程序不支持此功能.有关对SQL Server会话提供程序进行哪些更改以支持跨应用程序会话,请参阅此SO帖子.

我不会使用session来管理这个共享状态(即LastSiteUsed).此信息应与用户配置文件存储(成员资格,配置文件提供程序,自定义数据库等)保持一致.由于会话可能会过期 - 跨应用程序使用共享会话不是跟踪持久用户特定状态的可靠机制.如果持久性并不比将AppFabric Cache用于内存中跨应用程序共享状态更重要.