簡體   English   中英

Infinispan @CacheEntryExpired偵聽器-事件觸發兩次

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM