我们在Spring Boot应用程序中使用ehcache。我们的春季启动版本是2.0.3.RELEASE,而spring-boot-starter-cache 2.0.3.RELEASE使用ehcache 3.5.2。
我们使用ehcache的动机是,它既符合jsr107标准,又提供了堆支持。
以下是我们的spring配置:
@Configuration
@ConditionalOnWebApplication
@EnableCaching
public class CacheConfig {
@Autowired
private ApplicationContext context;
@Bean
public JCacheManagerFactoryBean jCacheManagerFactoryBean() throws IOException {
JCacheManagerFactoryBean jCacheManagerFactoryBean = new JCacheManagerFactoryBean();
Resource resource = context.getResource("classpath:mts/ehcache.xml");
jCacheManagerFactoryBean.setCacheManagerUri(resource.getURI());
return jCacheManagerFactoryBean;
}
@Bean
public JCacheCacheManager ehCacheCacheManager() throws IOException {
Properties props = System.getProperties();
props.setProperty(Caching.JAVAX_CACHE_CACHING_PROVIDER, "org.ehcache.jsr107.EhcacheCachingProvider");
JCacheCacheManager jCacheCacheManager = new JCacheCacheManager();
jCacheCacheManager.setCacheManager(jCacheManagerFactoryBean().getObject());
jCacheCacheManager.setTransactionAware(true);
return jCacheCacheManager;
}
}
我们在生产中面临的问题是,对于中等大小的磁盘持久性缓存,removeAll操作中出现以下java.io.EOFException错误:
Error : RuntimeException: java.io.EOFException
java.lang.RuntimeException: java.io.EOFException
at org.terracotta.offheapstore.disk.storage.FileBackedStorageEngine$FileChunk.readKeyBuffer(FileBackedStorageEngine.java:541) ~[ehcache-3.5.2.jar!/:3.5.2 7941fa2573343b31ae56a12564404552c6d6eff0]
at org.terracotta.offheapstore.disk.storage.FileBackedStorageEngine.readKeyBuffer(FileBackedStorageEngine.java:265) ~[ehcache-3.5.2.jar!/:3.5.2 7941fa2573343b31ae56a12564404552c6d6eff0]
at org.terracotta.offheapstore.storage.PortabilityBasedStorageEngine.readKey(PortabilityBasedStorageEngine.java:119) ~[ehcache-3.5.2.jar!/:3.5.2 7941fa2573343b31ae56a12564404552c6d6eff0]
at org.terracotta.offheapstore.OffHeapHashMap$DirectEntry.<init>(OffHeapHashMap.java:1540) ~[ehcache-3.5.2.jar!/:3.5.2 7941fa2573343b31ae56a12564404552c6d6eff0]
at org.terracotta.offheapstore.OffHeapHashMap$EntryIterator.create(OffHeapHashMap.java:1518) ~[ehcache-3.5.2.jar!/:3.5.2 7941fa2573343b31ae56a12564404552c6d6eff0]
at org.terracotta.offheapstore.OffHeapHashMap$EntryIterator.create(OffHeapHashMap.java:1511) ~[ehcache-3.5.2.jar!/:3.5.2 7941fa2573343b31ae56a12564404552c6d6eff0]
at org.terracotta.offheapstore.OffHeapHashMap$HashIterator.next(OffHeapHashMap.java:1407) ~[ehcache-3.5.2.jar!/:3.5.2 7941fa2573343b31ae56a12564404552c6d6eff0]
at org.terracotta.offheapstore.AbstractLockedOffHeapHashMap$LockedEntryIterator.next(AbstractLockedOffHeapHashMap.java:399) ~[ehcache-3.5.2.jar!/:3.5.2 7941fa2573343b31ae56a12564404552c6d6eff0]
at org.terracotta.offheapstore.AbstractLockedOffHeapHashMap$LockedEntryIterator.next(AbstractLockedOffHeapHashMap.java:392) ~[ehcache-3.5.2.jar!/:3.5.2 7941fa2573343b31ae56a12564404552c6d6eff0]
at org.terracotta.offheapstore.concurrent.AbstractConcurrentOffHeapMap$AggregateIterator.next(AbstractConcurrentOffHeapMap.java:553) ~[ehcache-3.5.2.jar!/:3.5.2 7941fa2573343b31ae56a12564404552c6d6eff0]
at org.ehcache.impl.internal.store.offheap.AbstractOffHeapStore$1.next(AbstractOffHeapStore.java:499) ~[ehcache-3.5.2.jar!/:3.5.2 7941fa2573343b31ae56a12564404552c6d6eff0]
at org.ehcache.impl.internal.store.offheap.AbstractOffHeapStore$1.next(AbstractOffHeapStore.java:489) ~[ehcache-3.5.2.jar!/:3.5.2 7941fa2573343b31ae56a12564404552c6d6eff0]
at org.ehcache.core.EhcacheBase$Jsr107CacheBase.removeAll(EhcacheBase.java:708) ~[ehcache-3.5.2.jar!/:3.5.2 7941fa2573343b31ae56a12564404552c6d6eff0]
at org.ehcache.jsr107.Eh107Cache.removeAll(Eh107Cache.java:304) ~[ehcache-3.5.2.jar!/:3.5.2 7941fa2573343b31ae56a12564404552c6d6eff0]
at com.mycompany.myproject.services.cache.service.impl.CacheService.doClearCacheWithName(CacheService.java:56) ~[MyProjectServicesCache_classes.jar!/:?]
在调用removeAll操作的代码中没有什么特别的。只需获取具有名称的缓存并调用清除所有内容即可:
private void doClearCacheWithName(String cacheName) {
Cache<Object, Object> cache = cacheManager.getCache(cacheName);
if (cache == null) {
throw new MyProjectException(String.format("Cache with name : %s does not exist!", cacheName));
}
logger.info(String.format("Clearing cache with name : %s", cacheName));
cache.removeAll();
}
这是ourBigCache的生产配置:
<cache alias="ourBigCache">
<expiry>
<ttl unit="seconds">21600</ttl>
</expiry>
<resources>
<heap unit="entries">1000</heap>
<disk unit="MB">4096</disk>
</resources>
</cache>
我们既不能在本地也不能在测试环境中复制它。
请注意,此缓存具有很高的使用率(生产中的读取计数很高),但我想这应该没有什么区别。
我找不到任何类似的报告问题。可以预见一些非常老的磁盘问题,但是它们太旧且不相似:
https://sourceforge.net/p/ehcache/discussion/322278/thread/e7a62df3/ http://forums.terracotta.org/forums/posts/list/2694.page
任何帮助将不胜感激。
致谢
答案 0 :(得分:1)
从我对ehcache-users的回复中复制:
这很可能只是https://github.com/ehcache/ehcache3/issues/2542的另一种症状,该症状已在74239a93e14eb7477841fffa36c971ef9e930686中修复了
很遗憾,此修复程序尚未在任何地方合并。如果您想接管,则可以削减自己的master版本(验证可能是一件好事)。否则,您将不得不等待3.7行上的第一个点发布(此时尚不知道时间线)。
克里斯