WEBAPI-利用AspNetWebApi-OutputCache並採用Redis建立Cache機制

利用AspNetWebApi-OutputCache並採用Redis建立Cache機制

除了他使用簡單以外,作者也提供了Interface讓你可彈性選擇你所需要採用哪種cahce Server( static Dictionary, Memcached, Redis...etc)

前一陣子剛好在觀看相關API  Cache的文章,

初步與 CacheCow 比較,發覺AspNetWebApi-OutputCache會比較適合目前的專案內容.

所以本篇還是以AspNetWebApi-OutputCache做介紹,至於Redis的安裝與操作就不在這裡多做贅述.

已有很多前輩分享了許多Redis相關的安裝與架設操作,這部分會放置參考連結中.

在此小弟如果有解釋的不好的地方,也請各位前輩多多指教!

 

 

其實會採用AspNetWebApi-OutputCache除了他使用簡單以外,

作者也提供了Interface讓你可彈性選擇你所需要採用哪種cahce Server( static Dictionary, Memcached, Redis...etc)

接下來就前置作業嚕!!

先直接到作者的git hub上看說明

AspNetWebApi-OutputCache

提供了.NET 4.0與4.5的版本可做選擇,可直接透過NUGET來做安裝.

再來就是安裝Redis Client

安裝好後就是來佈署嚕

在此介紹一下為什麼說使用簡單

如果單純只是要使用OutputCache

只需要在Controller內掛上標籤即可,

並依照需求設定

如下圖

依照作者說明如果沒指定的Sever Cache預設則是存放在System.Runtime.Caching.MemoryCache,

當然這不是我的需求,只是多話一下XD(使用上真的還滿方便的)

接下來就是主軸的部分了

假設我今天我已經架設好一台Redis Server 那我該如何指定將輸出的資料放置指定的Cache Server

如開頭所說,作者提供了Inteface讓我們能夠去實作指定的Cache Server

至於實作的部分,如果有些不瞭解.

有一位作者mackayj,佛心來著,

提供範例供大家參考使用

WebApi.OutputCache.Redis.ServiceStack

接下來就是實作繼承作者提供的Interface的部分嚕

先新增一個類別然後繼承IApiOutputCache並實作裡面的方法!

完整程式碼如下

using ServiceStack.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using WebApi.OutputCache.Core.Cache;

namespace WEBAPI_RedisCacheSample.MessageHandler
{
    public class ServiceStackRedisCacheProvider : IApiOutputCache
    {
        private readonly IRedisClient _client;

        public ServiceStackRedisCacheProvider(string host)
        {
            this._client = new RedisClient(host);
        }
        public ServiceStackRedisCacheProvider(string host, int port, string password = null, long db = 0L)
        {
            this._client = new RedisClient(host, port, password, db);
        }
        public ServiceStackRedisCacheProvider(IRedisClient client)
        {
           this._client = client;
        }
        public T Get<T>(string key) where T : class
        {

            return _client.Get<T>(key);
        }

        /// <summary>
        /// 先判斷是否有key值,沒有則新增(Add),有則提取資料(T Get<T>)
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool Contains(string key)
        {
            //在此假設如果有從redis中取得該筆資料,則不會進入Controller中
            //而是直接由T Get<T>從Redis將值取回傳出去
            return this.AllKeys.Contains(key);
        }
        public void Add(string key, object o, DateTimeOffset expiration, string dependsOnKey = null)
        {
          
            if (Equals(o, "")) return;
            //設定失效時間
            var expireTime = expiration.Subtract(DateTimeOffset.Now);


            lock (_client)
            {
                _client.Add(key, o, expireTime);
            }
        
        }
        public IEnumerable<string> AllKeys
        {
            get
            {
                return _client.GetAllKeys();
            }
        }
        #region 未實作部分
        public object Get(string key)
        {
            throw new NotImplementedException();
        }
        public void Remove(string key)
        {
            throw new NotImplementedException();

        }
        public void RemoveStartsWith(string key)
        {

            throw new NotImplementedException();
        }
        #endregion
    }
}

接下來是到App_Start中的WebApiConfig.cs去做註冊的動作嚕

註冊WebAPIConfig

 config.CacheOutputConfiguration().RegisterCacheOutputProvider(() => new ServiceStackRedisCacheProvider("localhost"));

或使用Autofac進行註冊

          var builder = new ContainerBuilder();
            builder.RegisterInstance(new ServiceStackRedisCacheProvider("localhost"));
            config.DependencyResolver = new AutofacWebApiDependencyResolver(builder.Build());

接下來就測試看看有沒有正常Work嚕

藉由POSTMAN分別呼叫API兩次,

在登入Redis中看是否有相關Key值

第一次執行有進入controller取值耗時133ms

第二次未進入controler中取值,而是直接從redis內取出耗時22ms

登入Redis中看資料是否有新增

在此附上完整程式碼

請點我

 

參考連結:
 ASP.NET Web API CacheOutput
 WebApi.OutputCache.Redis.ServiceStack
 Redis 系列文章 軟體主廚的程式料理廚房