利用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 系列文章 軟體主廚的程式料理廚房