AbpVnext使用分散式IDistributedCache Redis快取(自定義擴充套件方法)

天天向上518發表於2021-09-02

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或者不合理的地方,歡迎大家多多指教留言!!!

相關文章