EhCache + JGroups 给出“复制队列刷新异常:null”

发布于 2025-01-04 08:08:41 字数 4174 浏览 2 评论 0原文

我正在尝试使用基于 JGroups 的复制来配置 EhCache,但是一旦将第一个元素添加到缓存中,我就会收到以下异常的日志:

12061 [Replication Thread] ERROR net.sf.ehcache.distribution.RMIAsynchronousCacheReplicator - Exception on flushing of replication queue: null. Continuing...
java.lang.NullPointerException
    at net.sf.ehcache.distribution.RMISynchronousCacheReplicator.listRemoteCachePeers(RMISynchronousCacheReplicator.java:335)
    at net.sf.ehcache.distribution.RMIAsynchronousCacheReplicator.flushReplicationQueue(RMIAsynchronousCacheReplicator.java:299)
    at net.sf.ehcache.distribution.RMIAsynchronousCacheReplicator.replicationThreadMain(RMIAsynchronousCacheReplicator.java:119)
    at net.sf.ehcache.distribution.RMIAsynchronousCacheReplicator.access$100(RMIAsynchronousCacheReplicator.java:57)
    at net.sf.ehcache.distribution.RMIAsynchronousCacheReplicator$ReplicationThread.run(RMIAsynchronousCacheReplicator.java:371)

ehcache.xml 如下所示:

<?xml version="1.0" encoding="UTF-8"?>       
<ehcache 
  updateCheck="true" 
  monitoring="autodetect"
  defaultTransactionTimeoutInSeconds="30" 
  dynamicConfig="true">

  <cacheManagerPeerProviderFactory
    class="net.sf.ehcache.distribution.jgroups.JGroupsCacheManagerPeerProviderFactory"
    properties="jgroups.xml"
  />

  <defaultCache 
    maxElementsInMemory="200"
    eternal="false"
    statistics="true"
    timeToIdleSeconds="86400"
    timeToLiveSeconds="86400"    
    overflowToDisk="false">    
    <cacheEventListenerFactory
      class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
      properties="replicateAsynchronously=true, replicatePuts=true, replicateUpdates=true, replicateUpdatesViaCopy=true, replicateRemovals=true"
    />
    <bootstrapCacheLoaderFactory class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory" />    
  </defaultCache>

</ehcache>

jgroups.xml是这样的:

<?xml version='1.0'?>
<config>
    <TCP start_port="7800" />
    <TCPPING 
       timeout="3000" 
       initial_hosts="localhost[7800],localhost[7800]"
       port_range="10" 
       num_initial_members="2" />
    <VERIFY_SUSPECT timeout="1500" />
    <pbcast.NAKACK 
       use_mcast_xmit="false"
       gc_lag="100"
       retransmit_timeout="300,600,1200,2400,4800"
       discard_delivered_msgs="true" />
    <pbcast.STABLE
       stability_delay="1000"
       desired_avg_gossip="50000"
       max_bytes="400000" />
    <pbcast.GMS
       print_local_addr="true"
       join_timeout="5000"
       shun="false"
       view_bundling="true" />
</config>

使用jgroups版本2.8.1.GA,ehcache-core版本2.5.1,ehcache-jgroupsreplication版本1.5。

我做错了什么?

更新:当我更改为replicateAsynchronously=false时,出现以下异常:

Exception in thread "main" java.lang.NullPointerException
    at net.sf.ehcache.distribution.RMISynchronousCacheReplicator.listRemoteCachePeers(RMISynchronousCacheReplicator.java:335)
    at net.sf.ehcache.distribution.RMISynchronousCacheReplicator.replicatePutNotification(RMISynchronousCacheReplicator.java:145)
    at net.sf.ehcache.distribution.RMISynchronousCacheReplicator.notifyElementPut(RMISynchronousCacheReplicator.java:132)
    at net.sf.ehcache.event.RegisteredEventListeners.notifyListener(RegisteredEventListeners.java:294)
    at net.sf.ehcache.event.RegisteredEventListeners.invokeListener(RegisteredEventListeners.java:284)
    at net.sf.ehcache.event.RegisteredEventListeners.internalNotifyElementPut(RegisteredEventListeners.java:144)
    at net.sf.ehcache.event.RegisteredEventListeners.notifyElementPut(RegisteredEventListeners.java:122)
    at net.sf.ehcache.Cache.notifyPutInternalListeners(Cache.java:1515)
    at net.sf.ehcache.Cache.putInternal(Cache.java:1490)
    at net.sf.ehcache.Cache.put(Cache.java:1417)
    at net.sf.ehcache.Cache.put(Cache.java:1382)

更新2:问题是在 Terracota 的 JIRA 中创建的:https://jira.terracotta.org/jira/browse/EHC-927

I'm trying to configure EhCache with JGroups-based replication, but I get log flooded with the following exception as soon as first element is added to the cache:

12061 [Replication Thread] ERROR net.sf.ehcache.distribution.RMIAsynchronousCacheReplicator - Exception on flushing of replication queue: null. Continuing...
java.lang.NullPointerException
    at net.sf.ehcache.distribution.RMISynchronousCacheReplicator.listRemoteCachePeers(RMISynchronousCacheReplicator.java:335)
    at net.sf.ehcache.distribution.RMIAsynchronousCacheReplicator.flushReplicationQueue(RMIAsynchronousCacheReplicator.java:299)
    at net.sf.ehcache.distribution.RMIAsynchronousCacheReplicator.replicationThreadMain(RMIAsynchronousCacheReplicator.java:119)
    at net.sf.ehcache.distribution.RMIAsynchronousCacheReplicator.access$100(RMIAsynchronousCacheReplicator.java:57)
    at net.sf.ehcache.distribution.RMIAsynchronousCacheReplicator$ReplicationThread.run(RMIAsynchronousCacheReplicator.java:371)

ehcache.xml is like this:

<?xml version="1.0" encoding="UTF-8"?>       
<ehcache 
  updateCheck="true" 
  monitoring="autodetect"
  defaultTransactionTimeoutInSeconds="30" 
  dynamicConfig="true">

  <cacheManagerPeerProviderFactory
    class="net.sf.ehcache.distribution.jgroups.JGroupsCacheManagerPeerProviderFactory"
    properties="jgroups.xml"
  />

  <defaultCache 
    maxElementsInMemory="200"
    eternal="false"
    statistics="true"
    timeToIdleSeconds="86400"
    timeToLiveSeconds="86400"    
    overflowToDisk="false">    
    <cacheEventListenerFactory
      class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
      properties="replicateAsynchronously=true, replicatePuts=true, replicateUpdates=true, replicateUpdatesViaCopy=true, replicateRemovals=true"
    />
    <bootstrapCacheLoaderFactory class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory" />    
  </defaultCache>

</ehcache>

jgroups.xml is like this:

<?xml version='1.0'?>
<config>
    <TCP start_port="7800" />
    <TCPPING 
       timeout="3000" 
       initial_hosts="localhost[7800],localhost[7800]"
       port_range="10" 
       num_initial_members="2" />
    <VERIFY_SUSPECT timeout="1500" />
    <pbcast.NAKACK 
       use_mcast_xmit="false"
       gc_lag="100"
       retransmit_timeout="300,600,1200,2400,4800"
       discard_delivered_msgs="true" />
    <pbcast.STABLE
       stability_delay="1000"
       desired_avg_gossip="50000"
       max_bytes="400000" />
    <pbcast.GMS
       print_local_addr="true"
       join_timeout="5000"
       shun="false"
       view_bundling="true" />
</config>

Using jgroups version 2.8.1.GA, ehcache-core version 2.5.1, ehcache-jgroupsreplication version 1.5.

What am I doing wrong?

UPDATE: When I change to replicateAsynchronously=false I get the following exception:

Exception in thread "main" java.lang.NullPointerException
    at net.sf.ehcache.distribution.RMISynchronousCacheReplicator.listRemoteCachePeers(RMISynchronousCacheReplicator.java:335)
    at net.sf.ehcache.distribution.RMISynchronousCacheReplicator.replicatePutNotification(RMISynchronousCacheReplicator.java:145)
    at net.sf.ehcache.distribution.RMISynchronousCacheReplicator.notifyElementPut(RMISynchronousCacheReplicator.java:132)
    at net.sf.ehcache.event.RegisteredEventListeners.notifyListener(RegisteredEventListeners.java:294)
    at net.sf.ehcache.event.RegisteredEventListeners.invokeListener(RegisteredEventListeners.java:284)
    at net.sf.ehcache.event.RegisteredEventListeners.internalNotifyElementPut(RegisteredEventListeners.java:144)
    at net.sf.ehcache.event.RegisteredEventListeners.notifyElementPut(RegisteredEventListeners.java:122)
    at net.sf.ehcache.Cache.notifyPutInternalListeners(Cache.java:1515)
    at net.sf.ehcache.Cache.putInternal(Cache.java:1490)
    at net.sf.ehcache.Cache.put(Cache.java:1417)
    at net.sf.ehcache.Cache.put(Cache.java:1382)

UPDATE 2: Issue is created in Terracota's JIRA: https://jira.terracotta.org/jira/browse/EHC-927

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

温柔女人霸气范 2025-01-11 08:08:41

正如 Chris 在 EHC927 中指出的那样,我使用了错误的 cacheEventListenerFactory 类。它应该是 net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory 而不是 net.sf.ehcache.distribution.RMICacheReplicatorFactory

As pointed out by Chris in EHC927 I was using wrong cacheEventListenerFactory class. It should be net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory instead of net.sf.ehcache.distribution.RMICacheReplicatorFactory.

神魇的王 2025-01-11 08:08:41

的源代码

我检查了 RMIAsynchronousCacheReplicator 类http://www.jarvana.com/jarvana/view/net/sf/ehcache/ehcache-core/2.1.0/ehcache-core-2.1.0-sources.jar!/net/sf /ehcache/distribution/RMIAsynchronousCacheReplicator.java?format=ok

调用flushReplicationQueue()时出现异常;它还应该检查replicationQueue != null,而不仅仅是replicationQueue.size() == 0。就像在 while 循环中测试线程的 alive() 所做的那样...

如果对象不存在或未初始化,它无法刷新对象...它如何知道该对象如果它不存在或未初始化,则是否为空?简单地捕获 NullPointerException 并不是告诉用户这一点的好方法!

/**
 * RemoteDebugger method for the replicationQueue thread.
 * <p/>
 * Note that the replicationQueue thread locks the cache for the entire time it is writing elements to the disk.
 */
private void replicationThreadMain() {
    while (true) {
        // Wait for elements in the replicationQueue
        while (alive() && replicationQueue != null && replicationQueue.size() == 0) {
            try {
                Thread.sleep(asynchronousReplicationInterval);
            } catch (InterruptedException e) {
                LOG.debug("Spool Thread interrupted.");
                return;
            }
        }
        if (notAlive()) {
            return;
        }
        try {
            if (replicationQueue.size() != 0) {
                flushReplicationQueue();
            }
        } catch (Throwable e) {
            LOG.error("Exception on flushing of replication queue: " + e.getMessage() + ". Continuing...", e);
        }
    }
}

代码的目的只是为了避免当线程在 while 循环中不执行任何操作时 CPU 空闲时间跳至 50%,如果 CPU 使用率一直在 50% 左右变化,则可能会导致用户认为 Encache 出现问题...

可能,您需要添加具有较小值(100 毫秒到 150 毫秒)的属性asynchronousReplicationInterval,以便可以构建复制队列。附加如下:

properties="replicateAsynchronously=true, 
replicatePuts=true, 
replicateUpdates=true, 
replicateUpdatesViaCopy=true, 
replicateRemovals=true, 
asynchronousReplicationInterval=100"

下面的 RMIAsynchronousCacheReplicator 构造函数中可能需要它:

/**
 * Constructor for internal and subclass use
 */
public RMIAsynchronousCacheReplicator(
        boolean replicatePuts,
        boolean replicatePutsViaCopy,
        boolean replicateUpdates,
        boolean replicateUpdatesViaCopy,
        boolean replicateRemovals,
        int asynchronousReplicationInterval) {
    super(replicatePuts,
            replicatePutsViaCopy,
            replicateUpdates,
            replicateUpdatesViaCopy,
            replicateRemovals);
    this.asynchronousReplicationInterval = asynchronousReplicationInterval;
    status = Status.STATUS_ALIVE;
    replicationThread.start();
}

也许,您可以暂时忽略该问题,并让其他人报告该错误(如果它被认为是错误的话)...我想知道为什么它说“继续……”后来……

I've checked the source code for RMIAsynchronousCacheReplicator class

http://www.jarvana.com/jarvana/view/net/sf/ehcache/ehcache-core/2.1.0/ehcache-core-2.1.0-sources.jar!/net/sf/ehcache/distribution/RMIAsynchronousCacheReplicator.java?format=ok

There is something not right when flushReplicationQueue() is called; it should also check for replicationQueue != null, not just replicationQueue.size() == 0. Just like what it does to test the thread's alive() in the while loop...

It cannot flush an object if the object does not exist or is not initialized...how can it know the object is empty or not if it does not even exist or is not initialized? Simply catching NullPointerException is not a nice way tell the user about it!

/**
 * RemoteDebugger method for the replicationQueue thread.
 * <p/>
 * Note that the replicationQueue thread locks the cache for the entire time it is writing elements to the disk.
 */
private void replicationThreadMain() {
    while (true) {
        // Wait for elements in the replicationQueue
        while (alive() && replicationQueue != null && replicationQueue.size() == 0) {
            try {
                Thread.sleep(asynchronousReplicationInterval);
            } catch (InterruptedException e) {
                LOG.debug("Spool Thread interrupted.");
                return;
            }
        }
        if (notAlive()) {
            return;
        }
        try {
            if (replicationQueue.size() != 0) {
                flushReplicationQueue();
            }
        } catch (Throwable e) {
            LOG.error("Exception on flushing of replication queue: " + e.getMessage() + ". Continuing...", e);
        }
    }
}

The intent of the code simply to avoid CPU idle time to jump to 50% when the thread does nothing in the while loop which it may lead the user to believe something is not right with Encache if the CPU usage evolves around 50% all the time...

Probably, you need to add the property asynchronousReplicationInterval with a small value (100 ms to 150 ms) so that replication queue can be built. Append it as follows:

properties="replicateAsynchronously=true, 
replicatePuts=true, 
replicateUpdates=true, 
replicateUpdatesViaCopy=true, 
replicateRemovals=true, 
asynchronousReplicationInterval=100"

It may be needed in the RMIAsynchronousCacheReplicator constructor below:

/**
 * Constructor for internal and subclass use
 */
public RMIAsynchronousCacheReplicator(
        boolean replicatePuts,
        boolean replicatePutsViaCopy,
        boolean replicateUpdates,
        boolean replicateUpdatesViaCopy,
        boolean replicateRemovals,
        int asynchronousReplicationInterval) {
    super(replicatePuts,
            replicatePutsViaCopy,
            replicateUpdates,
            replicateUpdatesViaCopy,
            replicateRemovals);
    this.asynchronousReplicationInterval = asynchronousReplicationInterval;
    status = Status.STATUS_ALIVE;
    replicationThread.start();
}

Maybe, you can just ignore the problem for the time being and let someone else report the bug if it is even considered a bug...I wonder why it says "Continuing..." later...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文