【.NET Core项目实战-统一认证平台】开篇及目录索引
上篇文章我们介绍了2种网关配置信息更新的方法和扩展Mysql存储,本篇我们将介绍如何使用Redis来实现网关的所有缓存功能,用到的文档及源码将会在GitHub上开源,每篇的源代码我将用分支的方式管理,本篇使用的分支为course3。
附文档及源码下载地址:[https://github.com/jinyancao/CtrAuthPlatform/tree/course3]
网关的一个重要的功能就是缓存,可以对一些不常更新的数据进行缓存,减少后端服务开销,默认Ocelot实现的缓存为本地文件进行缓存,无法达到生产环境大型应用的需求,而且不支持分布式环境部署,所以我们需要一个满足大型应用和分布式环境部署的缓存方案。Redis应该是当前应用最广泛的缓存数据库,支持5种存储类型,满足不同应用的实现,且支持分布式部署等特性,所以缓存我们决定使用Redis作为缓存实现。
本文将介绍使用CSRedisCore来实现Redis相关操作,至于为什么选择CSRedisCore,可参考文章[.NET Core开发者的福音之玩转Redis的又一傻瓜式神器推荐],里面详细的介绍了各种Redis组件比较及高级应用,并列出了不同组件的压力测试对比,另外也附CSRedisCore作者交流QQ群:8578575,使用中有什么问题可以直接咨询作者本人。
二、缓存扩展实现首先本地安装Redis和管理工具Redis Desktop Manager,本文不介绍安装过程,然后NuGet安装 CSRedisCore,现在开始我们重写IOcelotCache<T>的实现,新建InRedisCache.cs文件。
using Ctr.AhphOcelot.Configuration; using Ocelot.Cache; using System; using System.Collections.Generic; using System.Text; namespace Ctr.AhphOcelot.Cache { /// <summary> /// 金焰的世界 /// 2018-11-14 /// 使用Redis重写缓存 /// </summary> /// <typeparam></typeparam> public class InRedisCache<T> : IOcelotCache<T> { private readonly AhphOcelotConfiguration _options; public InRedisCache(AhphOcelotConfiguration options) { _options = options; CSRedis.CSRedisClient csredis; if (options.RedisConnectionStrings.Count == 1) { //普通模式 csredis = new CSRedis.CSRedisClient(options.RedisConnectionStrings[0]); } else { //集群模式 //实现思路:根据key.GetHashCode() % 节点总数量,确定连向的节点 //也可以自定义规则(第一个参数设置) csredis = new CSRedis.CSRedisClient(null, options.RedisConnectionStrings.ToArray()); } //初始化 RedisHelper RedisHelper.Initialization(csredis); } /// <summary> /// 添加缓存信息 /// </summary> /// <param>缓存的key</param> /// <param>缓存的实体</param> /// <param>过期时间</param> /// <param>缓存所属分类,可以指定分类缓存过期</param> public void Add(string key, T value, TimeSpan ttl, string region) { key = GetKey(region, key); if (ttl.TotalMilliseconds <= 0) { return; } RedisHelper.Set(key, value.ToJson(), (int)ttl.TotalSeconds); } public void AddAndDelete(string key, T value, TimeSpan ttl, string region) { Add(key, value, ttl, region); } /// <summary> /// 批量移除regin开头的所有缓存记录 /// </summary> /// <param>缓存分类</param> public void ClearRegion(string region) { //获取所有满足条件的key var data= RedisHelper.Keys(_options.RedisKeyPrefix + "-" + region + "-*"); //批量删除 RedisHelper.Del(data); } /// <summary> /// 获取执行的缓存信息 /// </summary> /// <param>缓存key</param> /// <param>缓存分类</param> /// <returns></returns> public T Get(string key, string region) { key= GetKey(region, key); var result = RedisHelper.Get(key); if (!String.IsNullOrEmpty(result)) { return result.ToObject<T>(); } return default(T); } /// <summary> /// 获取格式化后的key /// </summary> /// <param>分类标识</param> /// <param>key</param> /// <returns></returns> private string GetKey(string region,string key) { return _options.RedisKeyPrefix + "-" + region + "-" + key; } } }实现所有缓存相关接口,是不是很优雅呢?实现好缓存后,我们需要把我们现实的注入到网关里,在ServiceCollectionExtensions类中,修改注入方法。
/// <summary> /// 添加默认的注入方式,所有需要传入的参数都是用默认值 /// </summary> /// <param></param> /// <returns></returns> public static IOcelotBuilder AddAhphOcelot(this IOcelotBuilder builder, Action<AhphOcelotConfiguration> option) { builder.Services.Configure(option); //配置信息 builder.Services.AddSingleton( resolver => resolver.GetRequiredService<IOptions<AhphOcelotConfiguration>>().Value); //配置文件仓储注入 builder.Services.AddSingleton<IFileConfigurationRepository, SqlServerFileConfigurationRepository>(); //注册后端服务 builder.Services.AddHostedService<DbConfigurationPoller>(); //使用Redis重写缓存 builder.Services.AddSingleton<IOcelotCache<FileConfiguration>, InRedisCache<FileConfiguration>>(); builder.Services.AddSingleton<IOcelotCache<CachedResponse>, InRedisCache<CachedResponse>>(); return builder; }奈斯,我们使用Redis实现缓存已经全部完成,现在开始我们在网关配置信息增加缓存来测试下,看缓存是否生效,并查看是否存储在Redis里。