Hazelcast 3.6.1“没有适合类型的反序列化器”异常

Ayu*_*lik 5 serialization client kryo hazelcast

我正在使用 Hazelcast 3.6.1 从地图中读取。存储在地图中的对象类称为Schedule

我已经像这样在客户端配置了一个自定义序列化程序。

ClientConfig config = new ClientConfig();
SerializationConfig sc = config.getSerializationConfig();
sc.addSerializerConfig(add(new ScheduleSerializer(), Schedule.class));
...
private SerializerConfig add(Serializer serializer, Class<? extends Serializable> clazz) {
    SerializerConfig sc = new SerializerConfig();
    sc.setImplementation(serializer).setTypeClass(clazz);
    return sc;
}
Run Code Online (Sandbox Code Playgroud)

地图是这样创建的

private final IMap<String, Schedule> map = client.getMap("schedule");
Run Code Online (Sandbox Code Playgroud)

如果我使用 schedule id 作为键从地图中获取,则地图返回正确的值,例如

return map.get("zx81");
Run Code Online (Sandbox Code Playgroud)

如果我尝试使用 SQL 谓词,例如

return new ArrayList<>(map.values(new SqlPredicate("statusActive")));
Run Code Online (Sandbox Code Playgroud)

然后我收到以下错误

Exception in thread "main" com.hazelcast.nio.serialization.HazelcastSerializationException: There is no suitable de-serializer for type 2. This exception is likely to be caused by differences in the serialization configuration between members or between clients and members.
Run Code Online (Sandbox Code Playgroud)

自定义序列化器使用 Kryo 进行序列化(基于此博客http://blog.hazelcast.com/comparing-serialization-methods/

public class ScheduleSerializer extends CommonSerializer<Schedule> {

    @Override
    public int getTypeId() {
        return 2;
    }

    @Override
    protected Class<Schedule> getClassToSerialize() {
        return Schedule.class;
    }

}
Run Code Online (Sandbox Code Playgroud)

CommonSerializer 定义为

public abstract class CommonSerializer<T> implements StreamSerializer<T> {

    protected abstract Class<T> getClassToSerialize();

    @Override
    public void write(ObjectDataOutput objectDataOutput, T object) {
        Output output = new Output((OutputStream) objectDataOutput);
        Kryo kryo = KryoInstances.get();
        kryo.writeObject(output, object);
        output.flush(); // do not close!
        KryoInstances.release(kryo);
    }

    @Override
    public T read(ObjectDataInput objectDataInput) {
        Input input = new Input((InputStream) objectDataInput);
        Kryo kryo = KryoInstances.get();
        T result = kryo.readObject(input, getClassToSerialize());
        input.close();
        KryoInstances.release(kryo);
        return result;
    }

    @Override
    public void destroy() {
        // empty
    }
}
Run Code Online (Sandbox Code Playgroud)

我需要在服务器端做任何配置吗?我认为客户端配置就足够了。

我正在使用 Hazelcast 客户端 3.6.1 并运行一个节点/成员。

noc*_*ius 5

查询要求节点了解类,因为必须反序列化字节流才能访问属性并查询它们。这意味着当您想查询对象时,您还必须在服务器端部署模型类(和序列化程序)。

而当您使用基于键的访问时,我们不需要查看值(在我们比较键的字节数组时也不需要查看键),只需发送结果即可。这样,模型类和序列化程序都不必在 Hazelcast 节点上可用。

我希望这是有道理的。