建议
- 程序中使用的缓存,请在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生效,需要进行如下配置:
- 在management.endpoints.web里添加caches与metrics两个接口暴露,默认只暴露health、info。
1management:
2 endpoints:
3 web:
4 exposure:
5 include: info, health, metrics, caches
6
7
- 在spring.cache里指定cache-names的配置
1spring:
2 cache:
3 cache-names: books, rooms
4
5
如果不指定cache-names,spring cache metrics是不会生效的,因为spring是在加载的过程中来确认需要对哪些cache来监控,像Cacheable之类需要动态加入的cache,spring在加载过程中无法感知到。
- 对cache provider启动调用记录功能,以caffeine为例,在spec中加入recordStats,如下:
1spring:
2 cache:
3 cache-names: books, rooms
4 caffeine:
5 spec: recordStats
6
7
- 相关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
- 举例
- curl localhost:8080/actuator/metrics/ 访问所有支持的metrics
1{
2 "names":[
3 "jvm.memory.max",
4 "jvm.threads.states",
5 "process.files.max",
6 "jvm.gc.memory.promoted",
7 "cache.puts",
8 "cache.size",
9 "cache.evictions",
10 "system.load.average.1m",
11 "jvm.memory.used",
12 "jvm.gc.max.data.size",
13 "jvm.gc.pause",
14 "jvm.memory.committed",
15 "system.cpu.count",
16 "logback.events",
17 "http.server.requests",
18 "tomcat.global.sent",
19 "jvm.buffer.memory.used",
20 "cache.eviction.weight",
21 "tomcat.sessions.created",
22 "jvm.threads.daemon",
23 "system.cpu.usage",
24 "jvm.gc.memory.allocated",
25 "tomcat.global.request.max",
26 "tomcat.global.request",
27 "cache.gets",
28 "tomcat.sessions.expired",
29 "jvm.threads.live",
30 "jvm.threads.peak",
31 "tomcat.global.received",
32 "process.uptime",
33 "tomcat.sessions.rejected",
34 "process.cpu.usage",
35 "tomcat.threads.config.max",
36 "jvm.classes.loaded",
37 "jvm.classes.unloaded",
38 "tomcat.global.error",
39 "tomcat.sessions.active.current",
40 "tomcat.sessions.alive.max",
41 "jvm.gc.live.data.size",
42 "tomcat.threads.current",
43 "process.files.open",
44 "jvm.buffer.count",
45 "jvm.buffer.total.capacity",
46 "tomcat.sessions.active.max",
47 "tomcat.threads.busy",
48 "process.start.time"
49 ]
50}
51
52
- curl localhost:8080/actuator/metrics/cache.gets 访问缓存get情况
1{
2 "name":"cache.gets",
3 "description":"The number of times cache lookup methods have returned a cached value.",
4 "baseUnit":null,
5 "measurements":[
6 {
7 "statistic":"COUNT",
8 "value":0
9 }
10 ],
11 "availableTags":[
12 {
13 "tag":"result",
14 "values":[
15 "hit",
16 "miss"
17 ]
18 },
19 {
20 "tag":"cache",
21 "values":[
22 "rooms",
23 "books"
24 ]
25 },
26 {
27 "tag":"name",
28 "values":[
29 "rooms",
30 "books"
31 ]
32 },
33 {
34 "tag":"cacheManager",
35 "values":[
36 "cacheManager"
37 ]
38 }
39 ]
40}
41
42
- curl “localhost:8080/actuator/metrics/cache.gets?tag=result:hit&tag=cache:books” 获取名为books的cache的命中次数
1{
2 "name":"cache.gets",
3 "description":"The number of times cache lookup methods have returned a cached value.",
4 "baseUnit":null,
5 "measurements":[
6 {
7 "statistic":"COUNT",
8 "value":0
9 }
10 ],
11 "availableTags":[
12 {
13 "tag":"name",
14 "values":[
15 "books"
16 ]
17 },
18 {
19 "tag":"cacheManager",
20 "values":[
21 "cacheManager"
22 ]
23 }
24 ]
25}
26
27
定制化配置
默认coffeine.spec的配置是对全体配置的,如果要分开配置可以自定义实现CacheManager,参见common-spring-cache-configurer. 使用时,直接引入该jar包即可。
1 <dependency>
2 <groupId>com.iqiyi.intl.common</groupId>
3 <artifactId>common-spring-cache-configurer</artifactId>
4 <version>1.4.0-SNAPSHOT</version>
5 </dependency>
6
7
使用配置如下(替换掉原先的spring.cache的配置):
1cache.items:
2 - name: books
3 spec: recordStats,softValues, maximumSize=1,expireAfterWrite=100s
4 - name: rooms
5 spec: expireAfterWrite=50s, maximumSize=10000
6
7
CacheManager自定义实现如下:
1@Configuration
2@ConditionalOnClass({ Caffeine.class, CaffeineCacheManager.class })
3@EnableConfigurationProperties(CacheProperties.class)
4public class AutoCustomizedCaffeineCacheConfigurer {
5 @Autowired
6 private CacheProperties cacheProperties;
7
8 @Bean
9 @Primary
10 public CacheManager caffeineCacheManager() {
11 SimpleCacheManager cacheManager = new SimpleCacheManager();
12
13 List<CaffeineCache> caches = cacheProperties.getItems().stream()
14 .map(item -> new CaffeineCache(item.getName(), Caffeine.from(item.getSpec()).build()))
15 .collect(Collectors.toList());
16 cacheManager.setCaches(caches);
17 return cacheManager;
18 }
19}
20
21
缓存策略最佳配置
- 设置softvalues, 当JVM内存耗尽时,会触发GC,回收这些cache的内存,防止OOM。
- 设置size或weight,限定缓存的最大占用空间,保证系统正常运行。
- 设置ttl/tti,设置过期时间,根据业务实际场景决定时长。
可以这么理解:
首先通过size或者weight来确定缓存总共占用的最大空间,softValues是用于兜底策略,防止万一size/weight设置的不正确,导致的OOM。对于ttl/tti,则是针对业务场景,来保证数据的时效性,用于程序运行的正确性。
举例如下:
1cache.items:
2 - name: books
3 spec: softValues, maximumSize=1,expireAfterWrite=100s
4
5
说明:
- 所有的配置都是针对每一个cache生效的,对于cacheManager, 也就是会有多个cache,所以占用的内容空间也会增加多份。所以cache不能设置过大。
- ttl/tti说明,ttl (time to live), 即expireAfterWrite;tti (time to idle), 即expireAfterRead, 如果设置tti,则意味着,只要这个key直接被读到,则缓存会一直不失效,所以请慎用tti。
参考文档
- Spring cache annotations: some tips & tricks
- spring-boot中配置和使用Caffeine Cache
转载请注明:学时网 » Spring Cache监控配置与使用规范建议