前言 因项目中实际需要,需要对dotnet服务做横向扩展,但是Session默认存储在MemoryCache
中,无法实现多台服务器共享Session
,导致通过nginx
做负载均衡后出现跳登录的情况,因此需要使用Redis共享Session解决此问题。
实现 安装依赖
Microsoft.AspNetCore.DataProtection.StackExchangeRedis 6.0.35
Microsoft.Extensions.Caching.StackExchangeRedis 6.0.35
修改startup.cs/Program.cs 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public void ConfigureServices (IServiceCollection services ){ services.AddHttpContextAccessor(); services.AddMvc().AddSessionStateTempDataProvider(); services.AddHttpClient(); services.AddSessionService("CacheProvider" ); services.AddCacheService("CacheProvider" ); services.AddControllersWithViews(ConfigureMvcOptions) .AddNewtonsoftJson(options => { options.UseMemberCasing(); options.SerializerSettings.DateFormatHandling = Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat; }); }
services.AddSessionService(“CacheProvider”) 的实现方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 public static void AddSessionService (this IServiceCollection services, string key ){ using (ServiceProvider provider = services.BuildServiceProvider()) { IConfiguration configuration = provider.GetRequiredService<IConfiguration>(); if (configuration == null ) { throw new ArgumentNullException(nameof (IConfiguration)); } IConfigurationSection section = configuration.GetSection(key); if (!section.Exists()) { Console.WriteLine($"appsetting.json 文件中不存在 '{key} ' 配置项,如需使用redis缓存,请增加此配置。将使用系统缓存。" ); } CacheOptions options = section.Get<CacheOptions>(); if (options == null ) { Console.WriteLine($"读取appsetting.json中'{key} '配置项失败,请正确配置。将使用系统缓存" ); } if (options?.CacheType == CacheTypeEnum.Redis.ToString()) { Console.WriteLine($"将使用Redis缓存Session信息" ); var connStr = options.RedisConnectionString; var dic = connStr.Contains(',' ) && !connStr.Contains(';' ) ? connStr.SplitAsDictionary("=" , "," , true ) : connStr.SplitAsDictionary("=" , ";" , true ); var Server = dic["Server" ]?.Trim(); var UserName = dic["UserName" ]?.Trim(); var Password = dic["Password" ]?.Trim(); #region 配置说明 #endregion ConfigurationOptions redisConfigOption = new ConfigurationOptions(); redisConfigOption.EndPoints.Add(Server); redisConfigOption.AllowAdmin = false ; redisConfigOption.Password = Password; redisConfigOption.ConnectTimeout = 60000 ; redisConfigOption.ResponseTimeout = 60000 ; redisConfigOption.SyncTimeout = 60000 ; redisConfigOption.ReconnectRetryPolicy = new LinearRetry(1000 ); var redis = ConnectionMultiplexer.Connect(redisConfigOption); services.AddDataProtection() .SetApplicationName("YZ" ) .PersistKeysToStackExchangeRedis(redis, "DataProtection-Keys" ); services.AddStackExchangeRedisCache(options => { options.ConfigurationOptions = redisConfigOption; options.InstanceName = "YZ" ; }); } services.AddSession(options => { options.Cookie.Name = "YZ" ; options.IdleTimeout = TimeSpan.FromMinutes(60 * 60 ); options.Cookie.HttpOnly = true ; options.Cookie.IsEssential = true ; }); } }
services.AddCacheService(“CacheProvider”); 实现方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 public static void AddCacheService (this IServiceCollection services, string key ){ using (ServiceProvider provider = services.BuildServiceProvider()) { ICache cache = NewLife.Caching.Cache.Default; IConfiguration configuration = provider.GetRequiredService<IConfiguration>(); if (configuration == null ) { throw new ArgumentNullException(nameof (IConfiguration)); } IConfigurationSection section = configuration.GetSection(key); if (!section.Exists()) { Console.WriteLine($"appsetting.json 文件中不存在 '{key} ' 配置项,如需使用redis缓存,请增加此配置。将使用系统缓存。" ); } CacheOptions options = section.Get<CacheOptions>(); if (options == null ) { Console.WriteLine($"读取appsetting.json中'{key} '配置项失败,请正确配置。将使用系统缓存" ); } if (options?.CacheType == CacheTypeEnum.Redis.ToString()) { Console.WriteLine($"将使用Redis缓存" ); var redis = new FullRedis(); redis.Init(options.RedisConnectionString); cache = redis; } services.AddSingleton(cache); } }
按照以上的配置,就可以实现使用redis共享Session了。