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資料庫中
好了今天就先到這裡,下次有時間再更新,自學AbpVnext過程中難免會有一些bug或者不合理的地方,歡迎大家多多指教留言!!!