记一次使用Springboot自带缓存注解失效问题

背景:最近在忙规则引擎降级服务,一个从0到1的项目,这个项目是因为原有的规则引擎服务是在本地内网,最近由于网络的迁移导致和阿里云上的前端交易中心经常网络不通,而且由于原有的规则引擎服务的决策引擎内核是厂商提供的,导致在排查问题时困难重重,在经历了几次生产问题之后,公司CTO要求开发一个降级服务,便于在原有规则引擎出问题之后的自动熔断降级切换。我在动手搭建这个项目过程中,遇到过许许多多的小问题,这次先分享下,遇到的使用SpringBoot自带缓存注解失效的问题。因为规则引擎有很多配置的数据,为了提高相应效率,很多地方决定将数据放入缓存,本来打算使用Redis,但是之前的Redis集群是在线下的服务器,这次阿里云上如果搭建Redis还需要申请新的服务器,由于此次需要缓存的数据都是配置数据,所以选择用Springboot框架自带的缓存框架。

使用过程

1. 简单使用 在使用SpringBoot自带缓存的过程中对于被Spring管理的Bean,倒是没什么问题,Cacheable注解标识的方法会被Spring通过Aop的方式进行代理。
一般在使用SpringBoot自带的缓存时会配置一个CacheManage用于管理全局的缓存。
可以看到Spring自带支持的CacheManage管理器包括以下:
在这里插入图片描述

本次项目中采用的是Caffeine缓存,一个高性能,接近最佳的缓存库。

 * @description: 缓存配置
 * @author: zhanghailang
 * @date: 2021-4-15 10:19
 */
@Configuration
public class CacheConfig {
    @Bean("caffeineCacheManager")
    public CacheManager cacheManager(){
        CaffeineCacheManager cacheManager = new CaffeineCacheManager();
        cacheManager.setCaffeine(Caffeine.newBuilder()
                .expireAfterWrite(60, TimeUnit.SECONDS)
                .initialCapacity(100)
                .maximumSize(10000));
        return cacheManager;
    }
}





在使用缓存的类上指定CacheManager
在这里插入图片描述

在需要使用缓存的方法上使用@Cacheable的注解,此处方法的作用是读取配置的规则校验文件,对于校验文件。只有第一次请求才会从项目路径下读取,后面每次都从缓存存中获取,当然了由于我在上面CacheManage中配置了过期时间 60s,只是为了测试用,一般在生产上的话要根据当前业务量来考虑,脱离了业务来考虑的话就是耍流氓。
此处Key为入参,支持Spel表达式编写,如果没有接触过Spel表达式的可以看看:点击查看Spel表达式基础

在这里插入图片描述

当然简单的使用也可以不指定Key,SpringBoot很贴心的为你准备了默认的Key生成策略。此处SpringBoot默认是将所有参数当做Key的生成策略,另外Key的生成策略是可以在CacheManger中配置的
在这里插入图片描述
@CacheEvict删除当前指定缓存,此处我将allEntries配置为true,代表将所有Key都给清除
在这里插入图片描述

当然上面这些只是简单的使用,在本次项目中使用缓存基本上都是为了提升接口效率,缓存的数据基本也都是配置数据。
2. 问题描述
在项目中使用缓存的时候,在一个调用外部系统的方法中,为了防止相同的客户在短时间内的重复调用外部系统,如下图所示,我照往常一样,@Cacheable注解已加,Key值已改,自信一跑,卧槽 ,不对劲,为什么缓存失效了呢。
在这里插入图片描述
不应该啊,我想了下此处这个类是继承Aviator(一个轻量级的表达式框架)的AbstracFunction接口,用于实现自定义函数,有兴趣的可以看下Aviator的介绍:
Aviator https://www.cnblogs.com/csguo/p/7614893.html
而我加注解的地方正是Call方法
在这里插入图片描述
此处call方法调用的是Aviator内部父类的方法,会导致缓存失效。
所以我猜想应该是这里出了问题。
第一次尝试解决 我决定把调用外部系统的逻辑拆出来,独立成一个方法,在这个方法上加注解进行处理。如下图这种
在这里插入图片描述

在这里插入图片描述
但是我又自信满满的打脸了,缓存方法在当前类方法中自调用会导致缓存失效,这个和@Transactional注解类似。
第二次尝试解决 我决定使用在调用的时候再一次获取当前类的实例,AopContext.currentProxy(),获取当前类的代理实现类,再一次发起调用,果然缓存不在失效。问题解决了。
在这里插入图片描述

后记

此次规则引擎降级服务系统,我花了两周的时间从0到1,一个完整的SpringBott项目到前天终于基本搭建完成,包括缓存、注解、切面、自定义异常、异步线程池,集成Nacos,MB,Logback日志框架、RocketMQ消息队列,到最后部署到Linux环境,都是我一手完成的还是很有成就感的系统。整体逻辑并不复杂,配置一定数量的指定规则,并对每个投保请求进行校验。但是由于接口的实时性和并发性,所以还是有待考验,目前压测看TPS只能50以下。
在本次服务搭建开发过程中,有很多问题都是第一次的遇见,踩了很多坑,接下来有时间我会一一记录。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值