1.服务跟客户端初始化的时候需要添加缓存配置
var host = new ServiceHostBuilder()
.RegisterServices(builder =>
{
builder.AddMicroService(option =>
{
6 option .AddCache()//缓存初始化
28 });
}).Configure(build =>
build.AddCacheFile("cacheSettings.json", optional: false,reloadOnChange:true))
.UseStartup<Startup>()
.Build();
2.配置文件(服务端跟客户端都需要)
{
"CachingSettings": [
{
"Id": "ddlCache",
"Class": "Surging.Core.Caching.RedisCache.RedisContext,Surging.Core.Caching",
"InitMethod": "",
"Maps": null,
"Properties": [
{
"Name": "appRuleFile",
"Ref": "rule",
"Value": "",
"Maps": null
},
{
"Name": "dataContextPool",
"Ref": "ddls_sample",
"Value": "",
"Maps": [
{
"Name": "Redis",//redis配置
"Properties": [
{
"Name": null,
"Ref": null,
"Value": ":你的密码@你的ip:6379::1",//reids 内存数据库连接字符串传 后面的1 代表你当前连接的是哪个库
"Maps": null
}
]
},
{
"Name": "MemoryCache",//本机内存
"Properties": null
}
]
},
{
"Name": "defaultExpireTime",//默认超时时间
"Ref": "",
"Value": "",
"Maps": null
},
{
"Name": "connectTimeout",//连接超时时间
"Ref": "",
"Value": "",
"Maps": null
},
{
"Name": "minSize",
"Ref": "",
"Value": "",
"Maps": null
},
{
"Name": "maxSize",
"Ref": "",
"Value": "",
"Maps": null
}
]
}
]
}
3.服务端配置
[Command(RequestCacheEnabled = true)]
[InterceptMethod(CachingMethod.Get, Key = "GetUser_id_{0}", CacheSectionType = SectionType.ddlCache, Mode = CacheTargetType.Redis, Time = )]
Task<UserModel> GetUser(UserModel user);
(1)在容错规则里面配置开启缓存
(2)在缓存拦截器里面配置缓存的方法,key,类型,超时时间等等。。
(3)传递的方法参数如果是model类型,就需要设置 [CacheKey(1)]来标识缓存key, 比如传递UserModel,
设置UserId 为1,Name 为fanly, 设置的KEY为GetUserName_name_{1}
那么缓存的key就会生成GetUserName_name_fanly, key 如果设置为GetUserName_id_{0}
那么缓存的key就会生成GetUserName_id_1,传递的方法参数是string,int 类型就不需要设置 [CacheKey(1)]
(4)Remove模式下,移除的缓存是一个真个列表
public class UserModel
{
[CacheKey()]
public int UserId { get; set; }
[CacheKey()]
public string Name { get; set; }
public int Age { get; set; }
}
4.客户端调用配置
客户端初始化的时候 需要添加.AddClientIntercepted(typeof(CacheProviderInterceptor)),其中CacheProviderInterceptor是作者给我们实现的一个实例,代码如下:
public class CacheProviderInterceptor : CacheInterceptor
{
public override async Task Intercept(ICacheInvocation invocation)
{
var attribute =
invocation.Attributes.Where(p => p is InterceptMethodAttribute)
.Select(p => p as InterceptMethodAttribute).FirstOrDefault();
var cacheKey = invocation.CacheKey == null ? attribute.Key :
string.Format(attribute.Key ?? "", invocation.CacheKey);
await CacheIntercept(attribute, cacheKey, invocation);
} private async Task CacheIntercept(InterceptMethodAttribute attribute, string key, ICacheInvocation invocation)
{
ICacheProvider cacheProvider = null;
switch (attribute.Mode)
{
case CacheTargetType.Redis:
{
cacheProvider = CacheContainer.GetService<ICacheProvider>(string.Format("{0}.{1}",
attribute.CacheSectionType.ToString(), CacheTargetType.Redis.ToString()));
break;
}
case CacheTargetType.MemoryCache:
{
cacheProvider = CacheContainer.GetService<ICacheProvider>(CacheTargetType.MemoryCache.ToString());
break;
}
}
if (cacheProvider != null) await Invoke(cacheProvider, attribute, key, invocation);
} private async Task Invoke(ICacheProvider cacheProvider, InterceptMethodAttribute attribute, string key, ICacheInvocation invocation)
{
switch (attribute.Method)
{
case CachingMethod.Get:
{
var retrunValue = await cacheProvider.GetFromCacheFirst(key, async () =>
{
await invocation.Proceed();
return invocation.ReturnValue;
}, invocation.ReturnType, attribute.Time);
invocation.ReturnValue = retrunValue;
break;
}
default:
{
await invocation.Proceed();
var keys = attribute.CorrespondingKeys.Select(correspondingKey => string.Format(correspondingKey, invocation.CacheKey)).ToList();
keys.ForEach(cacheProvider.RemoveAsync);
break;
}
}
}
}
找到InterceptMethodAttribute 的配置属性根据配置的缓存类型 初始化ICacheProvider接口,这个接口是缓存的一些常用方法,(当然我们也直接可以在代码中或者这个接口的实例,从而在缓存计算一些值)
然后在Invoke方法里面执行缓存的方法
5.其他
关于缓存拦截 我目前的版本是0.7.0.1 是只能在调用代理的时候用使用。因为在代理的时候才会根据容错规则开启缓存开关 来决定执行是否走缓存拦截。新版本的http支持 实现了缓存拦截。所以有需要的小伙伴可以升个级试试看。
关于缓存的连接 也是通过注册中心来检查它的健康状态。
最后运行程序,得到结果