Spring Cache监控配置与使用规范的建议

 更新时间:2023年07月27日 11:10:21   作者:仍在奔跑的男人  
这篇文章主要介绍了Spring Cache监控配置与使用规范的建议,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

建议

  • 程序中使用的缓存,请在cache-names里指明,如此,可以通过配置文件来明白程序中用到了哪些spring cache。
  • 请尽量对每一个cache分别设置缓存策略,因为不用的cache其使用的场景与缓存对象大小都不一样。分别设置缓存请使用common-spring-cache-configuere。默认spring不支持。
  • 缓存策略建议阅读缓存策略最佳配置
  • Cacheable的sync无特殊情况都设置为true,这样,取数据时有类似LoadingCache的效果,同时利用computeIfAbsent方法实现了线程安全,也防止雪崩问题。

spring boot 2.x 监控设置

spring boot从1.x升级到2.x之后,原先在spring-boot-actuator里默认的一些metrics不在自动生效,而是将这些metrics的功能从spring-boot-actuator迁移到了micrometer.io项目里,作为一个独立的微服务监控项目维护。

为此,为了使spring cache的相关metrics生效,需要进行如下配置:

1.在management.endpoints.web里添加caches与metrics两个接口暴露

默认只暴露health、info。

management:
  endpoints:
    web:
      exposure:
        include: info, health, metrics, caches

2.在spring.cache里指定cache-names的配置

spring:
  cache:
    cache-names: books, rooms

如果不指定cache-names,spring cache metrics是不会生效的,因为spring是在加载的过程中来确认需要对哪些cache来监控,像Cacheable之类需要动态加入的cache,spring在加载过程中无法感知到。

3.对cache provider启动调用记录功能

以caffeine为例,在spec中加入recordStats,如下:

spring:
  cache:
    cache-names: books, rooms
    caffeine:
      spec: recordStats

4.相关url

  • /actuator/caches 获取cache manager内的cache实例
  • /actuator/metrics/cache.gets 获取cache内缓存对象的情况,包括hit/miss的情况,具体参考tags drillDown的使用方式https://docs.spring.io/spring-boot/docs/2.0.0.BUILD-SNAPSHOT/actuator-
  • api//html/#metrics-drilling-down
  • /actuator/metrics/cache.puts
  • /actuator/metrics/cache.eviction

5.举例

curl localhost:8080/actuator/metrics/ 访问所有支持的metrics

{
    "names":[
        "jvm.memory.max",
        "jvm.threads.states",
        "process.files.max",
        "jvm.gc.memory.promoted",
        "cache.puts",
        "cache.size",
        "cache.evictions",
        "system.load.average.1m",
        "jvm.memory.used",
        "jvm.gc.max.data.size",
        "jvm.gc.pause",
        "jvm.memory.committed",
        "system.cpu.count",
        "logback.events",
        "http.server.requests",
        "tomcat.global.sent",
        "jvm.buffer.memory.used",
        "cache.eviction.weight",
        "tomcat.sessions.created",
        "jvm.threads.daemon",
        "system.cpu.usage",
        "jvm.gc.memory.allocated",
        "tomcat.global.request.max",
        "tomcat.global.request",
        "cache.gets",
        "tomcat.sessions.expired",
        "jvm.threads.live",
        "jvm.threads.peak",
        "tomcat.global.received",
        "process.uptime",
        "tomcat.sessions.rejected",
        "process.cpu.usage",
        "tomcat.threads.config.max",
        "jvm.classes.loaded",
        "jvm.classes.unloaded",
        "tomcat.global.error",
        "tomcat.sessions.active.current",
        "tomcat.sessions.alive.max",
        "jvm.gc.live.data.size",
        "tomcat.threads.current",
        "process.files.open",
        "jvm.buffer.count",
        "jvm.buffer.total.capacity",
        "tomcat.sessions.active.max",
        "tomcat.threads.busy",
        "process.start.time"
    ]
}

curl localhost:8080/actuator/metrics/cache.gets 访问缓存get情况

{
    "name":"cache.gets",
    "description":"The number of times cache lookup methods have returned a cached value.",
    "baseUnit":null,
    "measurements":[
        {
            "statistic":"COUNT",
            "value":0
        }
    ],
    "availableTags":[
        {
            "tag":"result",
            "values":[
                "hit",
                "miss"
            ]
        },
        {
            "tag":"cache",
            "values":[
                "rooms",
                "books"
            ]
        },
        {
            "tag":"name",
            "values":[
                "rooms",
                "books"
            ]
        },
        {
            "tag":"cacheManager",
            "values":[
                "cacheManager"
            ]
        }
    ]
}

curl “localhost:8080/actuator/metrics/cache.gets?tag=result:hit&tag=cache:books” 获取名为books的cache的命中次数

{
    "name":"cache.gets",
    "description":"The number of times cache lookup methods have returned a cached value.",
    "baseUnit":null,
    "measurements":[
        {
            "statistic":"COUNT",
            "value":0
        }
    ],
    "availableTags":[
        {
            "tag":"name",
            "values":[
                "books"
            ]
        },
        {
            "tag":"cacheManager",
            "values":[
                "cacheManager"
            ]
        }
    ]
}

定制化配置

默认coffeine.spec的配置是对全体配置的,如果要分开配置可以自定义实现CacheManager,参见common-spring-cache-configurer. 使用时,直接引入该jar包即可。

        <dependency>
            <groupId>com.iqiyi.intl.common</groupId>
            <artifactId>common-spring-cache-configurer</artifactId>
            <version>1.4.0-SNAPSHOT</version>
        </dependency>

使用配置如下(替换掉原先的spring.cache的配置):

cache.items:
  - name: books
    spec: recordStats,softValues, maximumSize=1,expireAfterWrite=100s
  - name: rooms
    spec: expireAfterWrite=50s, maximumSize=10000

CacheManager自定义实现如下:

@Configuration
@ConditionalOnClass({ Caffeine.class, CaffeineCacheManager.class })
@EnableConfigurationProperties(CacheProperties.class)
public class AutoCustomizedCaffeineCacheConfigurer {
    @Autowired
    private CacheProperties cacheProperties;
    @Bean
    @Primary
    public CacheManager caffeineCacheManager() {
        SimpleCacheManager cacheManager = new SimpleCacheManager();
        List<CaffeineCache> caches = cacheProperties.getItems().stream()
                .map(item -> new CaffeineCache(item.getName(), Caffeine.from(item.getSpec()).build()))
                .collect(Collectors.toList());
        cacheManager.setCaches(caches);
        return cacheManager;
    }
}

缓存策略最佳配置

  • 设置softvalues, 当JVM内存耗尽时,会触发GC,回收这些cache的内存,防止OOM。
  • 设置size或weight,限定缓存的最大占用空间,保证系统正常运行。
  • 设置ttl/tti,设置过期时间,根据业务实际场景决定时长。

可以这么理解:

首先通过size或者weight来确定缓存总共占用的最大空间,softValues是用于兜底策略,防止万一size/weight设置的不正确,导致的OOM。对于ttl/tti,则是针对业务场景,来保证数据的时效性,用于程序运行的正确性。

举例如下:

cache.items:
  - name: books
    spec: softValues, maximumSize=1,expireAfterWrite=100s

说明:

  • 所有的配置都是针对每一个cache生效的,对于cacheManager, 也就是会有多个cache,所以占用的内容空间也会增加多份。所以cache不能设置过大。
  • ttl/tti说明,ttl (time to live), 即expireAfterWrite;tti (time to idle), 即expireAfterRead, 如果设置tti,则意味着,只要这个key直接被读到,则缓存会一直不失效,所以请慎用tti。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • java多线程编程学习(线程间通信)

    java多线程编程学习(线程间通信)

    下面小编就为大家带来一篇java多线程编程学习(线程间通信)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • Java语言ReadWriteLock特性实例测试

    Java语言ReadWriteLock特性实例测试

    这篇文章主要介绍了Java语言ReadWriteLock特性实例测试,分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下
    2018-02-02
  • springmvc处理模型数据Map过程解析

    springmvc处理模型数据Map过程解析

    这篇文章主要介绍了springmvc处理模型数据Map过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01
  • 如何用Maven开发Spring Boot项目详解

    如何用Maven开发Spring Boot项目详解

    SpringBoot是一个集成Spring框架优点的开源后台开发框架,自动化配置和内嵌容器等特性减少了配置工作量,使得开发者可以更加专注于业务逻辑,这篇文章主要介绍了如何用Maven开发Spring Boot项目,需要的朋友可以参考下
    2024-09-09
  • Java源码解析之接口Collection

    Java源码解析之接口Collection

    Collection是List、Queue和set的超集,它直接继承于Iterable,也就是说所有的Collection集合类都支持foreach循环.除此之外呢,Collection也是面向接口编程的典范,它可以在多种实现类间转换,这就是面向对象编程的厉害之处.接下来就随着小编一起去看看吧,需要的朋友可以参考下
    2021-05-05
  • Java使用JSONObject操作json实例解析

    Java使用JSONObject操作json实例解析

    这篇文章主要介绍了Java使用JSONObject操作json,结合实例形式较为详细的分析了Java使用JSONObject解析json数据相关原理、使用技巧与操作注意事项,需要的朋友可以参考下
    2020-04-04
  • 浅析Java和Scala中的Future

    浅析Java和Scala中的Future

    这篇文章主要介绍了Java和Scala中的Future的相关资料,需要的朋友可以参考下
    2017-10-10
  • 使用java批量写入环境变量的实现

    使用java批量写入环境变量的实现

    本文主要介绍了使用java批量写入环境变量,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-03-03
  • JDK数组阻塞队列源码深入分析总结

    JDK数组阻塞队列源码深入分析总结

    在这篇文章当中,我们将通过源码仔细为大家介绍一下JDK具体是如何实现数组阻塞队列的,文中的示例代码讲解详细,感兴趣的可以了解一下
    2022-08-08
  • spring cloud之eureka高可用集群和服务分区解析

    spring cloud之eureka高可用集群和服务分区解析

    这篇文章主要介绍了spring cloud之eureka高可用集群和服务分区解析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03

最新评论