为什么 apache ignite 没有反序列化 java.util.Collections$SetFromMap?

Why apache ignite is not deserializing the java.util.Collections$SetFromMap?

当我尝试将数据放入缓存时,Apache ignite 抛出以下异常,

Caused by: class org.apache.ignite.IgniteCheckedException: Failed to deserialize object with given class loader: [clsLdr=org.apache.ignite.internal.processors.cache.GridCacheDeploymentManager$CacheClassLoader@5d5b5fa7, err=Failed to deserialize object [typeName=java.util.Collections$SetFromMap]]
    Caused by: java.lang.reflect.InvocationTargetException
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at org.apache.ignite.internal.marshaller.optimized.OptimizedObjectInputStream.readSerializable(OptimizedObjectInputStream.java:608)
        ... 43 more
    Caused by: java.lang.ClassNotFoundException: com.example.springapachecache.HelloWorld

计划:

 package com.example.springapachecache;

 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.Ignition;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder;

 import java.util.*;

 public class HelloWorld {
 public static void main(String[] args) throws IgniteException {
    // Preparing IgniteConfiguration using Java APIs
    IgniteConfiguration cfg = new IgniteConfiguration();

    // The node will be started as a client node.
    cfg.setClientMode(true);

    // Classes of custom Java logic will be transferred over the wire from this app.
    cfg.setPeerClassLoadingEnabled(true);

    // Setting up an IP Finder to ensure the client can locate the servers.
    TcpDiscoveryMulticastIpFinder ipFinder = new TcpDiscoveryMulticastIpFinder();
    ipFinder.setAddresses(Collections.singletonList("127.0.0.1:47500..47509"));
    cfg.setDiscoverySpi(new TcpDiscoverySpi().setIpFinder(ipFinder));

    // Starting the node
    Ignite ignite = Ignition.start(cfg);
    IgniteCache<Integer, Set<String>> setCache = ignite.getOrCreateCache("mySetCache");
    System.out.println("setCache before: "+setCache.get(1));
    Set<String> meetingUuids = Collections.newSetFromMap(new LinkedHashMap<String, Boolean>() {
        // Set backed by LRU map.
        private static final long serialVersionUID = -8251614405342939979L;
        @Override
        protected boolean removeEldestEntry(Map.Entry<String, Boolean> eldest) {
            return size() > 1000;
        }
    });

    meetingUuids.add("meetingId");
   //        Set<String> meetingUuidSet = new HashSet<>(meetingUuids);
   //        setCache.put(3, meetingUuidSet);
    setCache.put(1, meetingUuids);
    System.out.println("setCache after: "+setCache.get(1));

    // Disconnect from the cluster.
    ignite.close();
}

}

使用简单的 linkedHashMap(Set meetingUuids = Collections.newSetFromMap(new LinkedHashMap()) 构建 Set 效果很好。 你能帮忙吗?

您在最后一段中暗示了问题。您可以在 Ignite 中存储 Sets,并且可以通过网络“对等 class 加载”代码。您不能 做的是对等class 加载“模型”中使用的代码,即用于定义缓存的任何class。在您的示例代码中,这是 Collections.newSetFromMap.

中的闭包

我认为在 Ignite 中存储您的自定义设置有点混乱。例如,您不能使用 SQL 查询集合。因此,最好的解决方案是以不同方式对数据建模。

如果你真的想走这条路,如果你把你的 class 的副本放在 server-side 上它应该可以。