【.NET Core项目实战-统一认证平台】第五章 网关篇-自定义缓存Redis (2)

为了验证缓存是否生效,修改测试服务api/values/{id}代码,增加服务器时间输出。

[HttpGet("{id}")] public ActionResult<string> Get(int id) { return id+"-"+DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); }

增加新的测试路由脚本,然后增加缓存策略,缓存60秒,缓存分类test_ahphocelot。

--插入路由测试信息 insert into AhphReRoute values(1,'/ctr/values/{id}','[ "GET" ]','','http','/api/Values/{id}','[{"Host": "localhost","Port": 9000 }]', '','','{ "TtlSeconds": 60, "Region": "test_ahphocelot" }','','','','',0,1); --插入网关关联表 insert into dbo.AhphConfigReRoutes values(1,2);

现在我们测试访问网关地址:7777/api/values/1,过几十秒后继续访问,结果如下。

【.NET Core项目实战-统一认证平台】第五章 网关篇-自定义缓存Redis

可以看出来,缓存已经生效,1分钟内请求都不会路由到服务端,再查询下redis缓存数据,发现缓存信息已经存在,然后使用Redis Desktop Manager查看Redis缓存信息是否存在,奈斯,已经存在,说明已经达到我们预期目的。

三、解决网关集群配置信息变更问题

前面几篇已经介绍了网关的数据库存储,并介绍了网关的2种更新方式,但是如果网关集群部署时,采用接口更新方式,无法直接更新所有集群端配置数据,那如何实现集群配置信息一致呢?前面介绍了redis缓存,可以解决当前遇到的问题,我们需要重写内部配置文件提取仓储类,使用redis存储。

我们首先使用redis实现IInternalConfigurationRepository接口,每次请求配置信息时直接从redis存储,避免单机缓存出现数据无法更新的情况。RedisInternalConfigurationRepository代码如下。

using Ctr.AhphOcelot.Configuration; using Ocelot.Configuration; using Ocelot.Configuration.Repository; using Ocelot.Responses; using System; using System.Collections.Generic; using System.Text; namespace Ctr.AhphOcelot.Cache { /// <summary> /// 金焰的世界 /// 2018-11-14 /// 使用redis存储内部配置信息 /// </summary> public class RedisInternalConfigurationRepository : IInternalConfigurationRepository { private readonly AhphOcelotConfiguration _options; private IInternalConfiguration _internalConfiguration; public RedisInternalConfigurationRepository(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>配置信息</param> /// <returns></returns> public Response AddOrReplace(IInternalConfiguration internalConfiguration) { var key = _options.RedisKeyPrefix + "-internalConfiguration"; RedisHelper.Set(key, internalConfiguration.ToJson()); return new OkResponse(); } /// <summary> /// 从缓存中获取配置信息 /// </summary> /// <returns></returns> public Response<IInternalConfiguration> Get() { var key = _options.RedisKeyPrefix + "-internalConfiguration"; var result = RedisHelper.Get<InternalConfiguration>(key); if (result!=null) { return new OkResponse<IInternalConfiguration>(result); } return new OkResponse<IInternalConfiguration>(default(InternalConfiguration)); } } }

redis实现后,然后在ServiceCollectionExtensions里增加接口实现注入。

builder.Services.AddSingleton<IInternalConfigurationRepository, RedisInternalConfigurationRepository>();

然后启动网关测试,可以发现网关配置信息已经使用redis缓存了,可以解决集群部署后无法同步更新问题。

四、如何清除缓存记录

实际项目使用过程中,可能会遇到需要立即清除缓存数据,那如何实现从网关清除缓存数据呢?在上篇中我们介绍了接口更新网关配置的说明,缓存的更新也是使用接口的方式进行删除,详细代码如下。

using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace Ocelot.Cache { [Authorize] [Route("outputcache")] public class OutputCacheController : Controller { private readonly IOcelotCache<CachedResponse> _cache; public OutputCacheController(IOcelotCache<CachedResponse> cache) { _cache = cache; } [HttpDelete] [Route("{region}")] public IActionResult Delete(string region) { _cache.ClearRegion(region); return new NoContentResult(); } } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zywyzf.html