使用State Server在不同的.NET版本之间共享会话状态

背景

  • 我们使用.NET 3.5在IIS 6(Win2003 Server)上运行一个网站:site1.mysite.local
  • 我们使用.NET 4.0在IIS 7(Win2008 Server)上运行第二个网站:site2.mysite.local

在每个站点上,web.config包含StateServer和相同的machineKey:

  

我们还有一个PostRequestHandlerExecute事件处理程序来修改“NET_SessionId”cookie以具有相同的根域和路径。

 cookie.Domain = ".mysite.local"; cookie.Path = "/"; 

在global.asax文件中,我们有以下代码来修改Application_Start事件中的App Name:

  protected void Application_Start(object sender, EventArgs e) { string applicationName = "mysiteapp"; // Change the Application Name in runtime. FieldInfo runtimeInfo = typeof(HttpRuntime).GetField("_theRuntime", BindingFlags.Static | BindingFlags.NonPublic); HttpRuntime theRuntime = (HttpRuntime)runtimeInfo.GetValue(null); FieldInfo appNameInfo = typeof(HttpRuntime).GetField("_appDomainAppId", BindingFlags.Instance | BindingFlags.NonPublic); appNameInfo.SetValue(theRuntime, applicationName); } 

结果

两个站点都返回相同的会话ID,但是当我们尝试在site1上设置会话值时,site2不会返回值。

站点1(site1.mysite.local)结果

 Session ID (Session.SessionID): a55jnfcscxd3f0hnwoik02pp Session Value: True 

站点2(site2.mysite.local)结果

 Session ID (Session.SessionID): a55jnfcscxd3f0hnwoik02pp Session Value: 

根据我的理解,State Server会根据SessionID cookie,机器密钥和我们尝试更新的应用程序名称的组合来锁定会话,因此它们在两个站点上都是相同的。 问题是,会话值不会在网站上共享。

为什么不将SQL Server模式用于会话状态?

我们可能不得不,但我们希望使用我们的状态服务器。

有没有人在多个服务器上使用多个Web应用程序的State Server取得了成功?

.NET 3.5和.NET 4运行不同版本的CLR。 对象序列化(用于在不使用InProc时存储会话状态)在.NET版本之间有所不同。 该对象很可能无法在另一个平台上反序列化,因此它会无声地丢弃它。 如果您也将SQL Server用作会话状态服务器,则会遇到同样的问题。

假设这是问题,那么您将不得不确保两个站点都在相同的.NET版本上,或者执行您自己的序列化到磁盘或SQL Server。

StateServer和SQLServer状态管理还使用应用程序路径 (除应用程序名称)创建会话数据的密钥。

由于两个应用程序都读取了cookie,因此您的应用程序显示相同的SessionID,但应用程序路径必须与在状态服务器上实际读取相同的会话数据相同。

您可以在Application_Start中为此变量添加额外的覆盖,将其更改为相同的值:

 FieldInfo appPathInfo = typeof(HttpRuntime).GetField("_appDomainAppPath", BindingFlags.Instance | BindingFlags.NonPublic); appPathInfo .SetValue(theRuntime, applicationName);