【问题标题】:Spring JCache logging cache hitsSpring JCache 记录缓存命中
【发布时间】:2019-03-19 10:39:54
【问题描述】:

我有一个方法,我通过添加@CacheResult 注释来添加缓存(我实际上创建了一个代理,因为我无法更改SomethingService 的原始实现):

@Service
public class SomethingServiceProxyImpl implements SomethingService {

    @Autowired
    @Qualifier("somethingService")
    SomethingService somethingService;

    @Override
    @CacheResult(cacheName = "somethingCache", exceptionCacheName = "somethingExceptionCache", cachedExceptions = { SomeException.class })
    public SomePojo someMethod(String someArg) {
        return somethingService.someMethod(someArg);
    }
}

我现在需要的是能够记录缓存命中,这意味着返回的结果是来自缓存的结果。我已经查看了 Spring Cache、JCache 和 EHCache(我使用的实现),我只找到了侦听(使用侦听器)以下事件的方法:CREATED、UPDATED、REMOVED、EVICTED、EXPIRED 但它们都没有缓存返回结果(非空)时的事件。

我真的不想更改实现以编程方式使用缓存而不是使用注释(我实际上有很多服务要更改,而不仅仅是一个),有没有好方法来记录这些到底有什么活动?

【问题讨论】:

  • JCache 不会为每个缓存命中产生一个事件。我认为只有拥有调用 cache.get 的代码才能跟踪缓存命中。
  • 我发现,遗憾的是,执行 cache.get 的代码在 Spring Framework 内部,它是 CacheResultInterceptor,它是一个包私有类。
  • 你有围绕缓存命中的业务逻辑吗?如果没有,您可以启用统计以获取累积的指标。
  • 客户端希望应用程序日志中的缓存命中,因此通过我们的 ELK,他可以在我们的 Kibana 上获取这些指标。最后我告诉客户端从缓存创建中减去请求以获得缓存命中。

标签: spring caching jcache jsr107


【解决方案1】:

关于那个话题的想法。可能前两个是最相关的:

不要:在 Spring 中执行的代码和缓存命中时的相应缓存是性能最关键的代码。这就是为什么在这种情况下让调用附加代码或者甚至有一个选项不是那么聪明的原因。在日志中接线会极大地影响您的性能。通常,对于导致缓存请求的所有内容(例如传入的 Web 请求),都已经登录了应用程序。要了解缓存是否正常工作,命中计数器就足够了。这可以通过 JCache JMX Statistics 获得。

日志适配器:使用 Spring,您可以编写一个缓存适配器,根据需要进行日志记录,并通过配置将其连接。粗略的想法:查看CacheManagerCache 接口。包装 CacheManager 创建缓存方法并返回一个带有日志记录的包装缓存。

通过 ExpiryPolicy 破解:当指定自定义 ExpiryPolicy 时,JCache 实现会在每次缓存访问时调用方法 getExpiryForAccess。但是,您不会获得有关所请求的实际密钥的任何信息。由于性能原因,我还建议远离自己的 ExpiryPolicy 实现。所以这只是为了完整性。

记录缓存/记录每次访问:如果您指定多个缓存,Spring 会一个接一个地调用它们。您可以连接一个虚拟缓存作为第一个缓存,它只记录访问。

【讨论】:

  • 谢谢,这真的很有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-13
  • 2017-01-15
  • 1970-01-01
  • 1970-01-01
  • 2013-11-05
  • 1970-01-01
相关资源
最近更新 更多