问题
I’m using Hazelcast 3.9 to cluster user sessions.
To serialize the session objects, I created a global serializer implemented with Kryo (or more precisely KryoReflectionFactorySupport that allow to serialize objects without default constructor).
public class GlobalKryoSerializer implements StreamSerializer<Object> {
//use ThreadLocal because Kryo is not thread safe
private static final InheritableThreadLocal <Kryo> kryoThreadLocal = new InheritableThreadLocal <Kryo>() {
@Override
protected Kryo initialValue() {
Kryo kryo = new KryoReflectionFactorySupport();
//Kryo uses its own class loader
kryo.setClassLoader(java.lang.Thread.currentThread().getContextClassLoader());
return kryo;
}
};
public GlobalKryoSerializer(){ }
public int getTypeId() {
return 123;
}
public void destroy() { }
public void write(ObjectDataOutput objectDataOutput, Object object) throws IOException {
Output output = new Output((OutputStream) objectDataOutput);
Kryo kryo = kryoThreadLocal.get();
kryo.writeClassAndObject(output, object);
output.flush();
}
public Object read(ObjectDataInput objectDataInput) throws IOException {
InputStream in = (InputStream) objectDataInput;
Input input = new Input(in);
Kryo kryo = kryoThreadLocal.get();
Object retVal = kryo.readClassAndObject(input);
return retVal;
}
}
Hazelcast.xml is similar to https://github.com/hazelcast/hazelcast/blob/master/hazelcast/src/main/resources/hazelcast-default.xml with global serializer configuration:
<serialization>
<portable-version>0</portable-version>
<serializers>
<global-serializer override-java-serialization="true"> GlobalKryoSerializer</global-serializer>
</serializers>
</serialization>
When the session is invalidated, Hazelcast fails to de-serialize with the error below (the “type number” varies from time to time):
com.hazelcast.nio.serialization.HazelcastSerializationException: There is no suitable de-serializer for type 16843028. This exception is likely to be caused by differences in the serialization configuration betw
een members or between clients and members.
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.newHazelcastSerializationException(AbstractSerializationService.java:236) ~[hazelcast-all-3.9.jar:3.9]
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.readObject(AbstractSerializationService.java:263) ~[hazelcast-all-3.9.jar:3.9]
at com.hazelcast.internal.serialization.impl.ByteArrayObjectDataInput.readObject(ByteArrayObjectDataInput.java:570) ~[hazelcast-all-3.9.jar:3.9]
at com.hazelcast.session.HazelcastSession.deserializeMap(HazelcastSession.java:141) ~[hazelcast-tomcat7-sessionmanager-1.1.2.jar:na]
at com.hazelcast.session.HazelcastSession.readData(HazelcastSession.java:127) ~[hazelcast-tomcat7-sessionmanager-1.1.2.jar:na]
at com.hazelcast.internal.serialization.impl.DataSerializableSerializer.readInternal(DataSerializableSerializer.java:158) ~[hazelcast-all-3.9.jar:3.9]
at com.hazelcast.internal.serialization.impl.DataSerializableSerializer.read(DataSerializableSerializer.java:105) ~[hazelcast-all-3.9.jar:3.9]
at com.hazelcast.internal.serialization.impl.DataSerializableSerializer.read(DataSerializableSerializer.java:50) ~[hazelcast-all-3.9.jar:3.9]
at com.hazelcast.internal.serialization.impl.StreamSerializerAdapter.read(StreamSerializerAdapter.java:48) ~[hazelcast-all-3.9.jar:3.9]
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.toObject(AbstractSerializationService.java:185) ~[hazelcast-all-3.9.jar:3.9]
at com.hazelcast.map.impl.proxy.MapProxySupport.toObject(MapProxySupport.java:1149) ~[hazelcast-all-3.9.jar:3.9]
at com.hazelcast.map.impl.proxy.MapProxyImpl.remove(MapProxyImpl.java:212) ~[hazelcast-all-3.9.jar:3.9]
at com.hazelcast.session.HazelcastSessionManager.remove(HazelcastSessionManager.java:328) ~[hazelcast-tomcat7-sessionmanager-1.1.2.jar:na]
at com.hazelcast.session.HazelcastSessionManager.remove(HazelcastSessionManager.java:294) ~[hazelcast-tomcat7-sessionmanager-1.1.2.jar:na]
at org.apache.catalina.session.StandardSession.expire(StandardSession.java:833) ~[catalina.jar:7.0.82]
at org.apache.catalina.session.StandardSession.expire(StandardSession.java:732) ~[catalina.jar:7.0.82]
at org.apache.catalina.session.StandardSession.invalidate(StandardSession.java:1264) ~[catalina.jar:7.0.82]
at org.apache.catalina.session.StandardSessionFacade.invalidate(StandardSessionFacade.java:183) ~[catalina.jar:7.0.82]
at org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler.logout(SecurityContextLogoutHandler.java:65) ~[spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
回答1:
Hazelcast's Tomcat Based Web Session Replication only supports Serializable
objects as Session objects when you need to cluster them. This requirement also applies when a global serializer is set up in the cluster configuration. Thus, you need to make your session objects Serializable
to make it work.
You can also find this requirement in the documentation: https://github.com/hazelcast/hazelcast-tomcat-sessionmanager#features-and-requirements
I've raised a Github issue on the repo regarding this request, please track the process from there: https://github.com/hazelcast/hazelcast-tomcat-sessionmanager/issues/38
回答2:
Adding Kryo to the global serializer didn't work for me. I had to add it as a regular serializer. Spring boot example:
Config config = new Config();
/* other hazelcast configs omittedfor brevity */
SerializerConfig kyroSerizlier = new SerializerConfig()
.setImplementation(new GlobalKryoSerializer())
.setTypeClass(Object.class);
config.getSerializationConfig().addSerializerConfig(kyroSerizlier);
来源:https://stackoverflow.com/questions/48428131/hazelcast-with-global-serializer-kryo-there-is-no-suitable-de-serializer-for