[英]Infinispan @CacheEntryExpired listener - event firing twice
我有一个通过infinispan cache .addListener()方法添加的CacheEntryExpired侦听器的实现。
条目到期时将触发监听器事件。 问题是,每次事件触发两次。
我使用调试器和cache.getListeners()验证了缓存不包含我的同一个侦听器的两个实例。 getListeners的结果是:
(java.util.Collections$UnmodifiableSet<E>) [org.infinispan.iteration.impl.LocalEntryRetriever$PartitionListener@666SAT, my.supercool.package.MyExpirationEventListenerImpl@666TAN]
因此,只有一名听众。 侦听器实现接口:
@Listener
public interface TokenExpirationEventListener<T> {
@CacheEntryExpired
public void entryExpired(CacheEntryExpiredEvent<String, T> event);
}
一个实现看起来像:
@Override
@CacheEntryExpired
public void entryExpired(CacheEntryExpiredEvent<String, T> event) {
CODE
}
但是从接口中删除@CacheEntryExpired和@Listener批注(只是尝试)并不会导致事件仅发生一次。
我做错了什么,我在每个条目到期事件上都得到两个事件?
infinispan版本是8.2.0.final。
EDIT2:我能够找到引起麻烦的所有配置。 允许重现该错误的代码是:
import java.util.concurrent.TimeUnit;
import org.infinispan.Cache;
import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.configuration.cache.ClusteringConfigurationBuilder;
import org.infinispan.configuration.cache.Configuration;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.configuration.global.GlobalConfigurationBuilder;
import org.infinispan.configuration.global.TransportConfigurationBuilder;
import org.infinispan.manager.DefaultCacheManager;
import org.infinispan.notifications.Listener;
import org.infinispan.notifications.cachelistener.annotation.CacheEntryExpired;
import org.infinispan.notifications.cachelistener.event.CacheEntryExpiredEvent;
@Listener
public class TestMain {
private Cache<String, String> cache;
public static void main(String[] args) throws Exception {
new TestMain().test();
}
private void test() throws Exception{
configureInfinispan();
cache.put("test", "test", 10, TimeUnit.SECONDS);
cache.put("test2", "test", 10, TimeUnit.SECONDS);
while(true){
Thread.sleep(100);
}
}
public void configureInfinispan(){
DefaultCacheManager defaultCacheManager = configureCachaManager();//globalConfigurationBuilder.build(), defaultConfigurationBuilder.build(), /*startNow*/ true)
Configuration conf = defaultCacheManager.getDefaultCacheConfiguration();
ConfigurationBuilder cacheConfigBuilder = new ConfigurationBuilder().read(conf);
cacheConfigBuilder.expiration().enableReaper().wakeUpInterval(5, TimeUnit.SECONDS); //to speed test results
duplicationReason2(cacheConfigBuilder);
defaultCacheManager.defineConfiguration("testCache", cacheConfigBuilder.build());
cache = defaultCacheManager.getCache("testCache");
cache.addListener(new TestMain());
System.out.println("conf");
}
public DefaultCacheManager configureCachaManager(){
GlobalConfigurationBuilder globalConfigurationBuilder = new GlobalConfigurationBuilder();
ConfigurationBuilder defaultConfigurationBuilder = new ConfigurationBuilder();
duplicationReason1(defaultConfigurationBuilder, globalConfigurationBuilder);
return new DefaultCacheManager(globalConfigurationBuilder.build(), defaultConfigurationBuilder.build(), true);
}
@CacheEntryExpired
public void entryExpired(CacheEntryExpiredEvent<String, String> event) {
System.out.println("Expired:" + event.getKey());
}
private void duplicationReason2(ConfigurationBuilder configurationBuilder) {
configurationBuilder.persistence() //enable persistence
.passivation(false)
.addSingleFileStore()
.location("C:/test/infinispan")
// Disable writing anything to the file except when we do shutdown
.maxEntries(0)
.shared(false)
.fetchPersistentState(true)
.async() //write-behind
.enable() //write-behind
.threadPoolSize(Runtime.getRuntime().availableProcessors()) //writing threads
.preload(true); //load data from file on startup
}
private void duplicationReason1(ConfigurationBuilder configurationBuilder, GlobalConfigurationBuilder globalConfigurationBuilder){
configureCacheOperationalMode(configurationBuilder);
configureTransport(globalConfigurationBuilder);
}
private void configureCacheOperationalMode(ConfigurationBuilder configurationBuilder) {
ClusteringConfigurationBuilder clusteringConfigurationBuilder = configurationBuilder.clustering();
clusteringConfigurationBuilder.cacheMode(CacheMode.REPL_ASYNC);
}
private void configureTransport(GlobalConfigurationBuilder globalConfigurationBuilder) {
TransportConfigurationBuilder transportConfigurationBuilder = globalConfigurationBuilder.transport().defaultTransport();
transportConfigurationBuilder.addProperty("configurationFile", "default-configs/default-jgroups-udp.xml");
}
}
运行此命令(很遗憾,之后您需要杀死自己的主线程)将导致事件打印两次。
有两种方法共同导致这种情况。 评论其中一个并留下第二个评论会导致事件触发一次。
这些方法分别命名为duplicationReason1和duplicationReason2。
也许在配置中有些我不了解的东西?
好了,我能够看到您添加的测试用例的情况,谢谢!
这是群集缓存atm中的错误。 我登录了[1]进行了研究,如果要更新,请遵循。
尽管我们可以解决重复问题,但是您仍然可能出现其他重复事件,因此您仍然应该能够处理它们。 何时生成副本的示例可以在“并发到期访问”下的[2]中找到。 因此,通常应该只忽略具有空值的到期事件。
[1] https://issues.jboss.org/browse/ISPN-6405 [2] http://blog.infinispan.org/2015/10/expiration-enhancements.html
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.