使用redis在多个服务器上共享会话

时间:2017-05-18 18:51:13

标签: redis asp.net-core .net-core stackexchange.redis

我正在.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商店中创建更多条目。这样做是不好的形式?应该注意的是,我不会存储用户详细信息,只存储用户响应和其他可重用信息。

0 个答案:

没有答案