gpt4 book ai didi

java - Infinispan @CacheEntryExpired 监听器 - 事件触发两次

转载 作者:行者123 更新时间:2023-12-02 03:49:17 26 4
gpt4 key购买 nike

我有一个通过 infinispan 缓存 .addListener() 方法添加的 CacheEntryExpired 监听器的 n 实现。

监听器事件在条目到期时触发。问题是,每次事件都会被触发两次。

我验证(使用调试器和cache.getListeners())缓存不包含我的同一监听器的两个实例。 getListeners的结果是:

     (java.util.Collections$UnmodifiableSet<E>) [org.infinispan.iteration.impl.LocalEntryRetriever$PartitionListener@666SAT, my.supercool.package.MyExpirationEventListenerImpl@666TAN]

所以只有一个听众。监听器实现接口(interface):

@Listener
public interface TokenExpirationEventListener<T> {

@CacheEntryExpired
public void entryExpired(CacheEntryExpiredEvent<String, T> event);
}

实现如下所示:

@Override
@CacheEntryExpired
public void entryExpired(CacheEntryExpiredEvent<String, T> event) {
CODE
}

但是从接口(interface)中删除 @CacheEntryExpired 和 @Listener 注释(只是尝试)并不会导致事件仅发生一次。

我做错了什么,我在每个条目到期事件上收到两个事件吗?

infinispan 版本是 8.2.0.final。

编辑2:我能够追踪到所有导致问题的配置。允许重现错误的代码是:

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

关于java - Infinispan @CacheEntryExpired 监听器 - 事件触发两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36014879/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com