ehcache RMI复制:java.rmi.NoSuchObjectException:表中没有此类对象

时间:2018-09-04 04:36:19

标签: spring replication rmi ehcache ehcache-2

我一直在网上寻找一种解决方案,但是找不到解决ehcache复制问题的方法。我在2台服务器(服务器1 = {A.A.A.A和服务器2 = B.B.B.B)之间使用手动rmi复制,但出现此错误:

2018-09-04 00:07:40,517 DEBUG [ehcache.distribution.RMICacheManagerPeerProvider] (req:) (Replication Thread:null) Lookup URL //B.B.B.B:40000/AddressDao
2018-09-04 00:07:40,522 WARN  [ehcache.distribution.RMIAsynchronousCacheReplicator] (req:) (Replication Thread:null) Unable to send message to remote peer.  Message was: no such object in table
java.rmi.NoSuchObjectException: no such object in table
    at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:283)
    at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:260)
    at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:161)
    at net.sf.ehcache.distribution.RMICachePeer_Stub.send(Unknown Source)
    at net.sf.ehcache.distribution.RMIAsynchronousCacheReplicator.writeReplicationQueue(RMIAsynchronousCacheReplicator.java:314)
    at net.sf.ehcache.distribution.RMIAsynchronousCacheReplicator.replicationThreadMain(RMIAsynchronousCacheReplicator.java:127)
    at net.sf.ehcache.distribution.RMIAsynchronousCacheReplicator.access$000(RMIAsynchronousCacheReplicator.java:58)
    at net.sf.ehcache.distribution.RMIAsynchronousCacheReplicator$ReplicationThread.run(RMIAsynchronousCacheReplicator.java:389)

版本

  • ehcache:2.10.5
  • 春天:4.3.9。发布
  • JDK:8

配置

Ehcache

ehcache.xml文件如下所示:

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:noNamespaceSchemaLocation="ehcache.xsd">
<cacheManagerEventListenerFactory
    class=""
    properties=""/>
<cacheManagerPeerProviderFactory
 class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
    properties="peerDiscovery=manual"
    propertySeparator="," />
<cacheManagerPeerListenerFactory
   class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
    properties="port=40000,remoteObjectPort=40001,hostName=A.A.A.A" />
<defaultCache
    maxElementsInMemory="10000"
    eternal="false"
    timeToIdleSeconds="120"
    timeToLiveSeconds="120"
    overflowToDisk="false"
    diskSpoolBufferSizeMB="30"
    maxElementsOnDisk="10000000"
    diskPersistent="false"
    diskExpiryThreadIntervalSeconds="120"
    memoryStoreEvictionPolicy="LRU"
    />
</ehcache>

春豆

RMI服务器已为ehcache 2.5及更高版本配置了Spring:

<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
    <property name="configLocation" value="classpath:ehcache.xml"/>
    <property name="shared" value="false"/>
    <property name="acceptExisting" value="true"/>
</bean>
<bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">
    <property name="locateExistingServerIfPossible" value="true"/>
</bean>

Java代码

创建缓存

要创建缓存,请参见以下代码段:

    final CacheManager cm = CacheManager.create();
    _cache = cm.getCache(getName()); // If the cache is configured in the ehcache XML

    if (_cache == null) {
        final int maxElements = NumbersUtil.parseInt(value, 0);
        final int live = NumbersUtil.parseInt((String)params.get("cache.time.to.live"), 300);
        int idle = NumbersUtil.parseInt((String)params.get("cache.time.to.idle"), 300);
        if (live > 0 && idle > live) {
            idle = live;
        }
        _cache = new Cache(getName(), maxElements, false, live == 0, live, idle);

        // Check if replication is enabled and add the replication if needed
        final CacheManagerPeerListener cacheManagerPeerListener = cm.getCachePeerListener("RMI");
        final CacheManagerPeerProvider cmPeerProvider = cm.getCacheManagerPeerProvider("RMI");
        if (cacheManagerPeerListener != null && cmPeerProvider != null) {
            _cache.getCacheEventNotificationService().registerListener(new RMIAsynchronousCacheReplicator(false, false, true, false, true, 1000, 1000));
        }
        cm.addCache(_cache);
        s_logger.info("Cache created: " + _cache.toString());
    }

缓存复制注册

服务器加入集群时的代码:

public void onServerJoined(List<? extends Server> nodeList, long selfNodeId) {
    final CacheManager cm = CacheManager.create();
    CacheManagerPeerProvider peerProvider = cm.getCacheManagerPeerProvider("RMI");
    if (peerProvider != null) {
        for (Server host : nodeList) {
            if (selfNodeId == host.getId()) {
                continue;
            }
            for (String cacheName : cm.getCacheNames()) {
                final String peerUrl = "//" + host.getServiceIP() + ":40000/" + cacheName;
                peerProvider.registerPeer(peerUrl);
            }
        }
    }
}

故障排除

使用此Java code,可以列出缓存:

$ java RmiPortNamesDisplay A.A.A.A 40000
Names bound to RMI registry at host A.A.A.A and port 40000:
    AddressDao
$ java RmiPortNamesDisplay B.B.B.B 40000
Names bound to RMI registry at host B.B.B.B and port 40000:
    AddressDao

在每个服务器的防火墙上打开了端口40000400001

在使用ehcache JMX管理器时,如果我从缓存中删除所有条目,则会引发异常(在顶部),并且不会在另一台服务器上清除缓存。

有人遇到了这个问题或有解决方案的提示吗?

1 个答案:

答案 0 :(得分:0)

我终于找到了导致此问题的原因。 JVM是从-Djava.rmi.server.hostname=127.0.0.1开始的,它不允许RMI服务器正确绑定。您可以删除该参数,也可以将其设置为ehcache用于复制的IP。

相关问题