You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Asp.net Core 2部署Service Fabric多机集群时登录会话丢失问题

解决ASP.NET Core 2部署Service Fabric后会话丢失与"记住我"失效问题

兄弟,你的这个问题太典型了——本地单节点测试完全正常,一上多节点Service Fabric集群就频繁要求重登,连续几次后才暂时稳定,连"记住我"都失效,这绝对是分布式环境下的会话一致性和负载均衡会话亲和性的锅!下面给你拆解原因和靠谱的解决办法:

核心问题根源

  • 默认内存会话不支持分布式:ASP.NET Core默认用内存存会话数据,每个Service Fabric节点的应用实例都有自己独立的内存池子。用户请求被负载均衡器分到不同节点时,新节点压根没有之前的会话信息,自然就会踢你重新登录。连续登录几次后暂时正常?那大概率是负载均衡器临时把你的请求粘到了同一个节点,但这完全是碰运气,根本不可靠。
  • "记住我"的Cookie验证没做分布式兼容:如果CookieAuthenticationOptions里的DataProtectionProvider没配置分布式密钥存储,每个节点的加密密钥都是独立的,其他节点根本解不开你登录时生成的"记住我"Cookie,直接就判定你没登录;另外如果Cookie的过期时间被误设成10分钟,那会话自然撑不了多久。
  • 负载均衡器没开会话亲和:Azure负载均衡器或者Service Fabric反向代理默认可能没启用会话亲和,请求会被随机扔到不同节点,会话丢失就是必然的。

一步步解决问题

1. 换成分布式会话存储(重中之重)

ASP.NET Core的会话和身份验证都依赖IDistributedCache,必须把默认的内存实现换成分布式的,比如Redis或者Azure Cosmos DB,让所有节点共享同一套会话数据:

用Redis做分布式缓存(最常用方案)

先装NuGet包:

Install-Package Microsoft.Extensions.Caching.StackExchangeRedis

然后在Startup.cs的ConfigureServices里配置:

public void ConfigureServices(IServiceCollection services)
{
    // 配置Redis缓存
    services.AddStackExchangeRedisCache(options =>
    {
        options.Configuration = "你的Redis连接字符串";
        options.InstanceName = "AspNetCoreSession_"; // 给会话键加个前缀,避免和其他应用冲突
    });

    // 配置会话
    services.AddSession(options =>
    {
        options.IdleTimeout = TimeSpan.FromHours(2); // 按需设置会话超时时间
        options.Cookie.HttpOnly = true;
        options.Cookie.IsEssential = true;
        options.Cookie.SameSite = SameSiteMode.Lax;
    });

    // 配置Cookie认证
    services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
        .AddCookie(options =>
        {
            options.LoginPath = "/Account/Login";
            options.LogoutPath = "/Account/Logout";
            options.ExpireTimeSpan = TimeSpan.FromDays(7); // "记住我"的有效期,按需调整
            options.SlidingExpiration = true;
            // 关键:让所有节点共用同一套加密密钥,不然其他节点解不开Cookie
            // 可以用共享文件存储,或者Azure Blob/Redis来存密钥
            options.DataProtectionProvider = DataProtectionProvider.Create(new DirectoryInfo(@"\\你的共享存储路径\keys"));
            // 如果用Azure,也可以用Blob存储:
            // options.DataProtectionProvider = DataProtectionProvider.Create(new AzureBlobStorageXmlRepository(new Uri("https://你的存储账户.blob.core.windows.net/keys/protection-keys")));
        });
}

还要记得在Configure中间件里启用会话和认证:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    // ...其他中间件(比如静态文件、错误页)
    app.UseSession(); // 必须在UseAuthentication之前
    app.UseAuthentication();
    app.UseMvc();
}

2. 给负载均衡器开会话亲和

如果你的应用是通过Azure负载均衡器或者Service Fabric反向代理对外暴露的,得开启会话亲和性,让同一客户端的请求尽量打到同一个节点:

  • Azure负载均衡器:找到VMSS对应的负载均衡器,在负载均衡规则里把"会话亲和性"改成"客户端IP",这样同一IP的请求会被路由到同一个节点,直到会话超时或者负载均衡器重新分配。
  • Service Fabric反向代理:如果用了反向代理,在应用的ServiceManifest.xml里给端点加上SessionAffinityEnabled="true":
<Resources>
  <Endpoints>
    <Endpoint Name="ServiceEndpoint" Protocol="http" Port="80" SessionAffinityEnabled="true" />
  </Endpoints>
</Resources>

3. 检查"记住我"的代码实现

确保登录的时候正确传了IsPersistent = true:

// 构建用户身份
var claimsIdentity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
claimsIdentity.AddClaim(new Claim(ClaimTypes.Name, "用户名"));
// ...添加其他用户Claim

// 登录,开启记住我
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, 
    new ClaimsPrincipal(claimsIdentity),
    new AuthenticationProperties
    {
        IsPersistent = true, // 必须设为true才会启用记住我
        ExpiresUtc = DateTimeOffset.UtcNow.AddDays(7)
    });

4. 确认节点时钟同步

虽然概率不高,但Service Fabric集群的所有VM节点必须时钟同步,不然Cookie的过期时间校验会出错,导致会话提前失效。Azure VMSS默认会启用时间同步,但还是可以手动检查一下,确保所有节点的时间一致。

总结

先搞定分布式会话存储和DataProtection密钥共享,这是多节点环境下会话稳定的核心。配好分布式缓存后,再加上负载均衡的会话亲和性,就能彻底解决频繁重登和"记住我"失效的问题。之前连续登录几次后暂时正常,只是负载均衡临时把你粘到同一节点的巧合,根本不是解决办法哦。

内容的提问来源于stack exchange,提问作者Francesco Cristallo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 07:31:58