我设法加入EhCache和Terracota进行分布式集群(项目在https://github.com/ehcache/ehcache3/releases/download/v3.4.0/ehcache-clustered-3.4.0-kit.zip)并进行Spring配置集成,如:
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.cache.CacheManager;
import javax.cache.Caching;
import org.ehcache.clustered.client.config.ClusteredStoreConfiguration;
import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder;
import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder;
import org.ehcache.clustered.client.config.builders.ServerSideConfigurationBuilder;
import org.ehcache.clustered.common.Consistency;
import org.ehcache.config.builders.CacheConfigurationBuilder;
import org.ehcache.config.builders.ResourcePoolsBuilder;
import org.ehcache.config.units.MemoryUnit;
import org.ehcache.core.config.DefaultConfiguration;
import org.ehcache.expiry.Expirations;
import org.ehcache.jsr107.EhcacheCachingProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.jcache.JCacheCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import net.crezco.util.CustomProperties;
@Configuration
@EnableCaching
@Component
public class CacheConfig extends CachingConfigurerSupport {
private CustomProperties props;
private CacheManager cacheManager;
@Autowired
public CacheConfig(CustomProperties props) {
this.props = props;
}
@Bean
@Override
public org.springframework.cache.CacheManager cacheManager() {
cacheManager = createClusteredCacheManager();
return new JCacheCacheManager(cacheManager);
}
private CacheManager createClusteredCacheManager() {
URI clusterUri = URI.create(props.readCacheLocation());
Consistency consistency = Consistency.STRONG;
long sizeInMb = 10;
int ttl = 90; // 90s
long size = 100;
ClusteringServiceConfigurationBuilder clusteringServiceConfigurationBuilder = ClusteringServiceConfigurationBuilder.cluster(clusterUri);
ServerSideConfigurationBuilder serverSideConfigurationBuilder = (clusteringServiceConfigurationBuilder.autoCreate()).defaultServerResource("main");
ResourcePoolsBuilder.newResourcePoolsBuilder();
org.ehcache.config.CacheConfiguration<Object, Object> cacheConfiguration = CacheConfigurationBuilder
.newCacheConfigurationBuilder(Object.class, Object.class, ResourcePoolsBuilder.heap(size).with(ClusteredResourcePoolBuilder.clusteredDedicated(sizeInMb, MemoryUnit.MB)))
.withExpiry(Expirations.timeToLiveExpiration(new org.ehcache.expiry.Duration(ttl, TimeUnit.SECONDS))).add(new ClusteredStoreConfiguration(consistency)).build();
Map<String, org.ehcache.config.CacheConfiguration<?, ?>> caches = createCacheConfigurations(cacheConfiguration);
EhcacheCachingProvider provider = getCachingProvider();
DefaultConfiguration configuration = new DefaultConfiguration(caches, provider.getDefaultClassLoader(), serverSideConfigurationBuilder.build());
return provider.getCacheManager(provider.getDefaultURI(), configuration);
}
private Map<String, org.ehcache.config.CacheConfiguration<?, ?>> createCacheConfigurations(org.ehcache.config.CacheConfiguration<Object, Object> cacheConfiguration) {
Map<String, org.ehcache.config.CacheConfiguration<?, ?>> caches = new HashMap<>();
caches.put("iterableCountryCache", cacheConfiguration);
caches.put("elementCountryCache", cacheConfiguration);
return caches;
}
private EhcacheCachingProvider getCachingProvider() {
return (EhcacheCachingProvider) Caching.getCachingProvider();
}
}
然后,在经理上:
@Cacheable(cacheNames = "elementCountryCache", key = "#id + #langCode")
public CountryRes getById(Long id, User user, String langCode) {
return getByIdTemplate(id, user, langCode);
}
@Cacheable(cacheNames = "iterableCountryCache", key = "#query.toCacheKeyString()")
public Iterable<CountryRes> findAll(SearchQuery<CountryRes> query, User user, String langCode) {
return super.findAll(query, user, langCode);
}
@CacheEvict(value = "iterableCountryCache", allEntries = true)
public CountryRes save(CountryRes res, User user, String langCode) {
return saveTemplate(res, user, langCode);
}
@Caching(evict = { @CacheEvict(value = "iterableCountryCache", allEntries = true), @CacheEvict(value = "elementCountryCache", key = "#res.getNativeId() + #langCode") })
public CountryRes update(CountryRes res, User user, String langCode) {
return updateTemplate(res, user, langCode);
}
@Caching(evict = { @CacheEvict(value = "iterableCountryCache", allEntries = true), @CacheEvict(value = "elementCountryCache", allEntries = true) })
public void deleteById(Long id, User user) {
deleteTemplate(id, user);
}
缓存似乎正常工作。测试时(Junit或手动启动tomcat)findAll&amp; findById函数在第一次尝试后会加速。
但是在尝试保存时会发生异常:
java.lang.UnsupportedOperationException: Implement me
at org.ehcache.clustered.client.internal.store.ClusteredStore.iterator(ClusteredStore.java:463)
at org.ehcache.impl.internal.store.tiering.TieredStore.iterator(TieredStore.java:243)
at org.ehcache.core.Ehcache$Jsr107CacheImpl.removeAll(Ehcache.java:832)
at org.ehcache.jsr107.Eh107Cache.removeAll(Eh107Cache.java:311)
at org.springframework.cache.jcache.JCacheCache.clear(JCacheCache.java:108)
at org.springframework.cache.interceptor.AbstractCacheInvoker.doClear(AbstractCacheInvoker.java:113)
at org.springframework.cache.interceptor.CacheAspectSupport.performCacheEvict(CacheAspectSupport.java:457)
at org.springframework.cache.interceptor.CacheAspectSupport.processCacheEvicts(CacheAspectSupport.java:445)
at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:402)
at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:314)
at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:61)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)
at net.crezco.service.core.CountryManager$$EnhancerBySpringCGLIB$$d444b04b.save(<generated>)
at net.crezco.service.core.CountryManagerTest.createCountryCached(CountryManagerTest.java:217)
at net.crezco.service.core.CountryManagerTest.testBadUpdate(CountryManagerTest.java:123)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:73)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
这里有什么想法吗?非常感谢你提前。
答案 0 :(得分:0)
似乎删除.with(ClusteredResourcePoolBuilder.clusteredDedicated(sizeInMb,MemoryUnit.MB))可以完全访问迭代器。但我不知道为什么也不知道原因,因为它不适合它。