15

背景

  • 我们有一个使用 .NET 3.5 在 IIS 6(Win2003 服务器)上运行的网站:site1.mysite.local
  • 我们还有一个使用 .NET 4.0 在 IIS 7(Win2008 服务器)上运行的网站:site2.mysite.local

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

<sessionState mode="StateServer" stateConnectionString="tcpip=STATESRV01:42424" />

<machineKey decryptionKey="EDCDA6DF458176504BBCC720B4E29348E252E652591179E2" validationKey="CC482ED6B5D3569819B3C8F07AC3FA855B2FED7F0130F55D8405597C796457A2F5162D35C69B61F257DB5EFE6BC4F6CEBDD23A4112C4519F55185CB5EB3DFE61"/>

我们还有一个 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: 

问题

据我了解,状态服务器通过 SessionID cookie、机器密钥和我们尝试更新的应用程序名称的组合来关闭会话,因此在两个站点之间它是相同的。问题是,会话值不会在网站之间共享。

为什么不使用 SQL Server 模式进行会话状态?

我们可能不得不这样做,但我们希望改用我们的状态服务器。

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

4

2 回答 2

4

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

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

于 2012-09-05T23:49:44.943 回答
3

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

由于两个应用程序正在读取 cookie,您的应用程序显示相同的 SessionID,但是应用程序路径也必须相同才能在状态服务器上实际读取相同的会话数据。

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

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

appPathInfo .SetValue(theRuntime, applicationName);
于 2012-09-06T01:38:36.723 回答