AbpVnext使用分布式IDistributedCache緩存from Redis(帶自定義擴展方法)
首先搭好Docker中的Redis環境(個人測試環境):
我的依賴包的主要版本以及Redis依賴如下
1:添加依賴
<PackageReference Include="Volo.Abp.Caching.StackExchangeRedis" Version="3.0.5" /> <ItemGroup> <PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" /> <PackageReference Include="Microsoft.Extensions.PlatformAbstractions" Version="1.1.0" /> <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.9.5" /> <PackageReference Include="Serilog.Extensions.Hosting" Version="3.1.0" /> <PackageReference Include="Serilog.Sinks.Async" Version="1.4.0" /> <PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" /> <PackageReference Include="Serilog.Sinks.Elasticsearch" Version="8.2.0" /> <PackageReference Include="Serilog.Sinks.File" Version="4.1.0" /> <PackageReference Include="SqlSugar.IOC" Version="1.4.0" /> <PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="5.5.1" /> <PackageReference Include="Swashbuckle.AspNetCore.SwaggerUi" Version="5.5.1" /> <PackageReference Include="Volo.Abp.AspNetCore" Version="3.0.5" /> <PackageReference Include="Volo.Abp.AspNetCore.Authentication.JwtBearer" Version="3.0.5" /> <PackageReference Include="Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared" Version="3.0.5" /> <PackageReference Include="Volo.Abp.AspNetCore.Serilog" Version="3.0.5" /> <PackageReference Include="Volo.Abp.Autofac" Version="3.0.5" /> <PackageReference Include="Volo.Abp.UI.Navigation" Version="3.0.5" /> //添加AbpVnext分布式redis緩存依賴包 <PackageReference Include="Volo.Abp.Caching.StackExchangeRedis" Version="3.0.5" /> </ItemGroup>
2:配置信息。默認在appsetting.json中配置即可,格式如下:
"Redis": { //Redis:Configuration "IsEnabled": "true",
//該服務將會吧數據存儲在DB7的數據庫中
"Configuration": "171.74.78.153:6379,password=9966686@,defaultdatabase=7"
}
3:在hosting模塊中添加依賴
using Volo.Abp.Caching.StackExchangeRedis; namespace GDBS.MonitoringService.HttpApi.Hosting { [DependsOn( typeof(AbpAutofacModule), typeof(AbpAspNetCoreMvcModule), typeof(AbpAspNetCoreAuthenticationJwtBearerModule) , typeof(IdentityEntityFrameworkCoreModule) , typeof(MonitoringHttpApiModule) , typeof(MonitoringApplicationContractsModule) , typeof(SharedToolKitsModule) , typeof(JketSharedDomainModule) , typeof(AbpCachingStackExchangeRedisModule)//這里新增依賴模塊 )] public class MonitoringHttpApiHostingModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { //測試時下面配置了還出不來,寫入沒有效果??這里就直接在配置文件中處理了。 //service.AddStackExchangeRedisCache(redisoptions => //{ // redisoptions.Configuration = configuration["Redis:Configuration"]; // redisoptions.ConfigurationOptions = new StackExchange.Redis.ConfigurationOptions // { // ConnectTimeout = 10 // //EndPoints=new StackExchange.Redis.EndPointCollection { // //} // }; //}); } }
4:Controller中的主要代碼
namespace GDBS.ProvincialLevelService.HttpApi.Controller { /// <summary> /// ProvincialLevelService 省級服務 /// </summary> [Authorize] [Area("ProvincialLevelService")] [Route("api/ProvincialLevelService/[Controller]")] public class ProvincialLevelDataInfoController : AbpController { private readonly IBridgeTestDataService _service; private readonly IBridgeTestDataService _service; private readonly IHttpClientFactory _httpClientFactory; private readonly IHttpContextAccessor _httpContext; private readonly IFilesInfoService _filesInfoservice; /// <summary> /// /// </summary> /// <param name="service"></param> /// <param name="httpClientFactory"></param> /// <param name="httpContext"></param> public ProvincialLevelDataInfoController(IBridgeTestDataService service, IHttpClientFactory httpClientFactory, IHttpContextAccessor httpContext, IFilesInfoService filesInfoservice) { _service = service; _httpClientFactory = httpClientFactory; _httpContext = httpContext; _filesInfoservice = filesInfoservice; } /// <summary> /// TestRedisAddString /// </summary> /// <param name="key"></param> /// <param name="redisvalue"></param> /// <returns></returns> [HttpGet("TestRedisAddString")] [AllowAnonymous] public async Task<OutputDto> TestRedisAddString(string key, string redisvalue) { try { await _service.DoTestRedis(key, redisvalue); return OutputDto.ToResultSuccess(msg: "ok"); } catch (Exception ex) { return OutputDto.ToResultFail(ex.Message); } } } }
5:Application中,通常我們在這里來注入分布式接口
using Microsoft.Extensions.Caching.Distributed; namespace GDBS.ProvincialLevelService.Application.AppService { public class BridgeTestDataService : ApplicationService, IBridgeTestDataService { private readonly IDistributedCache _distributedCache; public BridgeTestDataService(IDistributedCache distributedCache) { _distributedCache = distributedCache; } public async Task<string> DoTestRedis(string key, string redisvalue) { try { await _distributedCache.SetStringAsync(key,redisvalue); return "ok"; } catch (Exception ex) { return $"錯誤{ex.Message}"; } } } }
6:為了方便直接在Controller中注入測試,通常我們需要在Application中注入使用
/// <summary> /// _cacheServer 通常我們在Application里面注冊,這里只是測試 /// </summary> private readonly IDistributedCache _cacheServer; public ProvincialLevelDataInfoController(IDistributedCache cacheServer) { _cacheServer = cacheServer; } /// <summary> /// TestRedisAddString /// </summary> /// <param name="key"></param> /// <param name="redisvalue"></param> /// <param name="ab_hd">true絕對過期,false:滑動過期</param> /// <returns></returns> [HttpGet("TestRedisAddString2")] [AllowAnonymous] public async Task<OutputDto> TestRedisAddString2(string key, string redisvalue, bool ab_hd = true) { try { await _cacheServer.SetStringAsync(key, redisvalue, RedisPolicyHelper.GetRedisProcily(ab_hd,60)); return OutputDto.ToResultSuccess(msg: "ok"); } catch (Exception ex) { return OutputDto.ToResultFail(ex.Message); } }
7:分布式緩存的策略,使用絕對還是滑動過期,不使用策略就默認為長期保存,可以使用控制方法
using Microsoft.Extensions.Caching.Distributed; using System; namespace GDBS.Shared.ToolKits.Tool { public class RedisPolicyHelper { /// <summary> /// 使用絕對還是滑動過期,不使用策略就默認為長期保存 /// </summary> /// <param name="ab_hd">true絕對過期; false:滑動過期</param> /// <param name="Seconds">默認60秒過期</param> /// <returns></returns> public static DistributedCacheEntryOptions GetRedisProcily(bool ab_hd, int Seconds = 60) { var policy = new DistributedCacheEntryOptions(); Seconds = Seconds <= 1 ? 60 : Seconds; if (ab_hd) policy.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(Seconds); else policy.SlidingExpiration = TimeSpan.FromSeconds(Seconds); return policy; } } }
8:自定義分布式緩存擴展方法
using System; using System.Threading.Tasks; using Newtonsoft.Json; using Microsoft.Extensions.Caching.Distributed; namespace GDBS.Shared.ToolKits { public static class RedisDistributeExtension { /// <summary> /// 自定義IDistribute 分布式擴展方法 jason 同步方法 /// </summary> /// <typeparam name="TModel"></typeparam> /// <param name="cache"></param> /// <param name="key"></param> /// <param name="handler"></param> /// <returns></returns> public static TModel RedisGetOrCreate<TModel>(this IDistributedCache cache, string key, Func<DistributedCacheEntryOptions, TModel> handler) { TModel t; string vs = cache.GetString(key); if (string.IsNullOrEmpty(vs)) { var options = new DistributedCacheEntryOptions(); t = handler.Invoke(options); cache.SetString(key, JsonConvert.SerializeObject(t), options); } else { t = JsonConvert.DeserializeObject<TModel>(vs); } return t; } /// <summary> /// 自定義IDistribute 分布式擴展方法 jason 異步方法 /// </summary> /// <typeparam name="TModel"></typeparam> /// <param name="cache"></param> /// <param name="key"></param> /// <param name="handler"></param> /// <returns></returns> public static async Task<TModel> RedisGetOrCreateAsync<TModel>(this IDistributedCache cache, string key, Func<DistributedCacheEntryOptions, Task<TModel>> handler) { TModel t; var vs = await cache.GetStringAsync(key); if (string.IsNullOrEmpty(vs)) { var options = new DistributedCacheEntryOptions(); t = await handler.Invoke(options); await cache.SetStringAsync(key, JsonConvert.SerializeObject(t), options); } else { t = JsonConvert.DeserializeObject<TModel>(vs); } return t; } } }
9:測試自定義擴展方法,Controller中的主要code。
/// <summary> /// 自定義分布式緩存的擴展方法,沒有緩存就設置緩存,有就直接獲取 /// </summary> /// <param name="key"></param> /// <param name="redisvalue"></param> /// <param name="ab_hd"></param> /// <returns></returns> [HttpGet("TestRedisAddString3")] [AllowAnonymous] public async Task<OutputDto> TestRedisAddString3(string key, string redisvalue, bool ab_hd = true) { try { await _cacheServer.RedisGetOrCreateAsync<string>(key, (options) => { options.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(30); return Task.Factory.StartNew(() => { return $"_cacheServer.RedisGetOrCreateAsync獲取或者設置緩存的方法:{redisvalue},時間:{DateTime.Now}"; }); }); return OutputDto.ToResultSuccess(msg: "ok"); } catch (Exception ex) { return OutputDto.ToResultFail(ex.Message); } }
10:調用自定義分布式擴展方法
11:測試結果部分主要截圖:
12:公司一微服務系統中有多個服務,我們將不同的服務緩存數據將來存儲在不同的Redis數據庫中
好了今天就先到這里,下次有時間再更新,如果存在不合理的地方,歡迎大家多多指教留言!!!