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

基于Redis实现两个C#微服务间Session共享的问题排查与解决

问题原因分析
  • Redis缓存键前缀不统一:AuthMicroservice使用AuthMicroservice:作为Redis缓存的实例名称,所有Session数据会以这个前缀存储;而GameMicroservice使用GameMicroservice:作为前缀,导致它只能查找自身前缀下的Session键,无法读取Auth服务写入的数据。
  • DataProtection未统一应用隔离标识:ASP.NET Core的DataProtection默认会以应用程序名称作为加密隔离边界,若两个微服务未指定相同的应用名称,即使共享DataProtectionKeys,也无法解密对方生成的Session Cookie,进而无法正确关联Redis中的Session数据。
正确实现Session共享的配置方案

要实现跨微服务的Session共享,需要保证三个核心配置统一:DataProtection应用名称、Redis缓存实例名称、Session Cookie配置。

步骤1:统一DataProtection配置

在两个微服务的AddDataProtection中添加SetApplicationName,指定相同的全局标识,确保加密解密逻辑一致:

builder.Services.AddDataProtection()
    .SetApplicationName("SharedSession_App") // 统一应用名称,必须完全一致
    .PersistKeysToStackExchangeRedis(redis, "DataProtectionKeys");

步骤2:统一Redis缓存实例名称

将两个服务的AddStackExchangeRedisCache中的InstanceName修改为相同的前缀,比如SharedSession:,这样Session数据会存储在同一组键下:

builder.Services.AddStackExchangeRedisCache(option =>
{
    option.Configuration = redisConnectionString;
    option.InstanceName = "SharedSession:"; // 统一前缀,替换原来的服务专属前缀
});

步骤3:确保Session Cookie配置一致

当前两个服务的Cookie配置已经统一(名称、过期时间等),如果微服务部署在不同子域名下,还需要添加Cookie的Domain配置,确保Cookie能跨子域名共享:

builder.Services.AddSession(options =>
{
    options.IdleTimeout = TimeSpan.FromDays(15);
    options.Cookie.MaxAge = TimeSpan.FromDays(15);
    options.Cookie.Name = "Session";
    options.Cookie.HttpOnly = true;
    options.Cookie.IsEssential = true;
    options.Cookie.Domain = ".yourdomain.com"; // 若跨子域名部署,需设置统一根域名
});

完整配置示例

AuthMicroservice修改后的配置

var redisConnectionString = builder.Configuration.GetConnectionString("RedisConnection");
var redis = redisConnectionString != null ? ConnectionMultiplexer.Connect(redisConnectionString) : null;

// 统一DataProtection配置
builder.Services.AddDataProtection()
    .SetApplicationName("SharedSession_App")
    .PersistKeysToStackExchangeRedis(redis, "DataProtectionKeys");

// 统一Redis缓存前缀
builder.Services.AddStackExchangeRedisCache(option =>
{
    option.Configuration = redisConnectionString;
    option.InstanceName = "SharedSession:";
});

// Session配置(保持一致,跨域需添加Domain)
builder.Services.AddSession(options =>
{
    options.IdleTimeout = TimeSpan.FromDays(15);
    options.Cookie.MaxAge = TimeSpan.FromDays(15);
    options.Cookie.Name = "Session";
    options.Cookie.HttpOnly = true;
    options.Cookie.IsEssential = true;
    // options.Cookie.Domain = ".yourdomain.com"; // 按需启用
});

GameMicroservice修改后的配置

var redisConnectionString = builder.Configuration.GetConnectionString("RedisConnection");
var redis = redisConnectionString != null ? ConnectionMultiplexer.Connect(redisConnectionString) : null;

// 统一DataProtection配置
builder.Services.AddDataProtection()
    .SetApplicationName("SharedSession_App")
    .PersistKeysToStackExchangeRedis(redis, "DataProtectionKeys");

// 统一Redis缓存前缀
builder.Services.AddStackExchangeRedisCache(option =>
{
    option.Configuration = redisConnectionString;
    option.InstanceName = "SharedSession:";
});

// Session配置(保持一致,跨域需添加Domain)
builder.Services.AddSession(options =>
{
    options.IdleTimeout = TimeSpan.FromDays(15);
    options.Cookie.MaxAge = TimeSpan.FromDays(15);
    options.Cookie.Name = "Session";
    options.Cookie.HttpOnly = true;
    options.Cookie.IsEssential = true;
    // options.Cookie.Domain = ".yourdomain.com"; // 按需启用
});
验证方式

修改配置后重启两个服务,在Auth服务中写入Session数据后,查看Redis中的键会以SharedSession:开头;在Game服务中请求时,HttpContext.Session.GetString("UserId")就能正确读取到对应值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 17:25:07