【问题标题】:Extending Spring Cache Interceptor for collecting custom metrics扩展 Spring Cache Interceptor 以收集自定义指标
【发布时间】:2021-08-20 15:31:38
【问题描述】:

我正在尝试详细收集缓存指标,例如将它们捕获为事件;对象从缓存中命中,或者未命中,花费了 X 毫秒,而不仅仅是聚合指标。由于 Spring Cache 抽象已经足够好,我想我会找到类似拦截器或过滤器的东西,但似乎没有。一个人将如何去做,在没有自己的情况下实现一个 CacheManager?作为参考,我将 Redis 缓存与 Lettuce 客户端一起使用,但更希望缓存抽象保留并在中心位置捕获缓存事件。

  • 对于 Spring 来说相对较新,我什至不确定执行这些操作的最佳方法是什么。我尝试创建我的 CacheManager 包装 redis 之一,但不确定它如何与自动配置一起使用。
  • 我自己的缓存管理器只是代理所有对包装的调用,但它不知道是缓存命中还是未命中,即使缓存为空,实际方法调用也会调用它们。

【问题讨论】:

  • 如果这是你的全部功能,它实际上会破坏正确的执行。您需要哪些开箱即用的指标?
  • 这不是完整的功能,它只是我试图匹配但无济于事的签名。我想捕获获取缓存需要多长时间,并将它们记录在其他地方,但我需要每个请求,因此我对聚合指标不感兴趣。

标签: java spring spring-boot spring-cache


【解决方案1】:

你在找RedisCache.getStatistics吗?

它返回CacheStatistics

public interface CacheStatistics {

    /**
     * @return the name of the {@link RedisCache}.
     */
    String getCacheName();

    /**
     * @return number of put operations on the cache.
     */
    long getPuts();

    /**
     * @return the total number of get operations including both {@link #getHits() hits} and {@link #getMisses() misses}.
     */
    long getGets();

    /**
     * @return the number of cache get hits.
     */
    long getHits();

    /**
     * @return number of cache get misses.
     */
    long getMisses();

    /**
     * @return the number of {@link #getGets() gets} that have not yet been answered (neither {@link #getHits() hit} nor
     *         {@link #getMisses() miss}).
     */
    default long getPending() {
        return getGets() - (getHits() + getMisses());
    }

    /**
     * @return number of cache removals.
     */
    long getDeletes();

    /**
     * @param unit the time unit to report the lock wait duration.
     * @return lock duration using the given {@link TimeUnit} if the cache is configured to use locking.
     */
    long getLockWaitDuration(TimeUnit unit);

    /**
     * @return initial point in time when started statistics capturing.
     */
    Instant getSince();

    /**
     * @return instantaneous point in time of last statistics counter reset. Equals {@link #getSince()} if never reset.
     */
    Instant getLastReset();

    /**
     * @return the statistics time.
     */
    default Instant getTime() {
        return Instant.now();
    }
}

【讨论】:

  • 我已经将它与使用我自己的 StatisticsCollector 相结合,使用默认线程模型,我可以使用 ThreadLocals 来收集每个请求的指标。但是我仍然缺乏测量持续时间的能力,但这可以通过复制(它的受保护类)DefaultRedisCacheWriterexecute 方法来实现。
【解决方案2】:

Lettuce 似乎没有提供测量缓存命中/未命中的可用性。
Lettuce 具有一些内置指标,例如直方图或延迟。 A link to the wiki.

您可以尝试从 redis 本身获取一些指标。看看redis-docs
在那里您可以获得更多数据,例如read/write hit/missevicted_objects

总而言之:我认为对象级指标(= 每个键指标?)并没有真正的帮助。你想知道,object-id-abcobject-id-def 的速度有多快?

但如果您真的需要:您可以使用自定义实现(proxy-pattern 或覆盖某些方法)自行将 RedisClient 定义为 bean。然后你可以测量时间。
我看不到从 redis 获取缓存命中/未命中的方法。也许您会在lettuce-github-repo 和/或redis-api 中找到一些东西。
您可以尝试使用执行时间将其存档(当获取值需要很长时间时,它可能不在缓存中),但这非常不稳定,您会得到很多误报。


编辑

作为另一个想法:在您的代理中,您可以存储请求密钥的频率(它应该像requests/hour 一样以时间单位来衡量)。结合执行时间,您接近cache hit/miss-metric。

【讨论】:

    猜你喜欢
    • 2022-06-14
    • 2019-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-21
    • 2021-07-08
    • 2020-10-15
    • 2011-04-19
    相关资源
    最近更新 更多