我正在.NET Core中实现分布式redis缓存,以便在微服务环境中的多个.NET Core服务之间共享。微服务位于IIS上负载均衡器后面的多个服务器上。 redis缓存将用于临时保存与各个用户相关的数据。 redis服务器将在内部托管。我已经有一个用于外部身份验证的cookie(AuthCookie),但我不使用Identity或Session,因为用户应该登录。我只是将AuthCookie发送到我的身份验证服务,它进行身份验证并填写我的ClaimsPrincipal结果。
由于我的缓存将是用户特定的,我认为将.Net Session与redis分布式缓存支持一起使用是个好主意。我想使用AuthCookie作为密钥,但它失败了,因为它不知道如何解密它,这很糟糕。因此,我必须有一个特定于.net会话的cookie。问题是,即使持有我的密钥,会话也不能在我的负载均衡器上的服务器上运行。这是我设置的简单版本:
public void ConfigureServices(IServiceCollection services)
{
var host = "127.0.0.1";
var port = "6379";
var conn = $"{host}:{port}";
var redis = ConnectionMultiplexer.Connect(conn);
services.AddDataProtection().PersistKeysToRedis(redis, "DataProtection-Keys");
services.AddDistributedRedisCache(options =>
{
options.Configuration = conn;
options.InstanceName = "master";
});
services.AddSession(options => options.CookieName = "NetSession");
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseSession();
app.UseMvc();
}
public class RedisController : Controller
{
public string Get(string key)
{
return HttpContext.Session.GetString(key);
}
public string Post([FromBody] CacheData data)
{
HttpContext.Session.SetString(data.Key, data.Value);
return $"Added {data.Key} with {data.Value}";
}
}
这在一台服务器上运行正常,但在我的负载均衡器上设置3个实例将无法正常工作。我调用负载均衡器,它在服务器A上设置一个密钥,redis将显示为masterSOMEGUID,并且将返回一个长的“NetSession”cookie。我打电话给负载平衡器,服务器B拿起它,“NetSession”被发送,但是当试图找到密钥时它会生成一个不同的GUID而无法找到它。如果我再次点击服务器A,它会发现没问题。我无法弄清楚我做错了什么。
我发现一个单独的解决方案是不使用Session,只使用IDistributedCache和已经在请求上的AuthCookie。
public class RedisController : Controller
{
private readonly IDistributedCache _cache;
public RedisController(IDistributedCache cache)
{
_cache = cache
}
public string Get(string key)
{
return _cache.GetString($"{HttpContext.Request.Cookies["NetSession"]}{key}");
}
public string Post([FromBody] CacheData data)
{
_cache.SetString($"{HttpContext.Request.Cookies["NetSession"]}{data.Key}", data.Value);
return $"Added {data.Key} with {data.Value}";
}
}
这显然会在redis商店中创建更多条目。这样做是不好的形式?应该注意的是,我不会存储用户详细信息,只存储用户响应和其他可重用信息。