我正在使用Hazelcast 3.9来集群用户会话。
为了序列化会话对象,我创建了一个用Kryo实现的全局序列化器(或者更确切地说是KryoReflectionFactorySupport,它允许在没有默认构造函数的情况下序列化对象)。
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与https://github.com/hazelcast/hazelcast/blob/master/hazelcast/src/main/resources/hazelcast-default.xml类似,具有全局序列化程序配置:
<serialization>
<portable-version>0</portable-version>
<serializers>
<global-serializer override-java-serialization="true"> GlobalKryoSerializer</global-serializer>
</serializers>
</serialization>
当会话无效时,Hazelcast无法通过以下错误反序列化(“类型编号”会不时变化):
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]
答案 0 :(得分:1)
Hazelcast的基于Tomcat的Web会话复制仅在您需要聚类时将Serializable
对象作为Session对象支持。在群集配置中设置全局序列化程序时,此要求也适用。因此,您需要设置会话对象Serializable
才能使其正常工作。
您还可以在文档中找到此要求:https://github.com/hazelcast/hazelcast-tomcat-sessionmanager#features-and-requirements
我已就此请求在回购时提出了Github问题,请从那里跟踪该过程:https://github.com/hazelcast/hazelcast-tomcat-sessionmanager/issues/38
答案 1 :(得分:0)
将Kryo添加到全局序列化器对我来说并不起作用。我不得不将它添加为常规序列化程序。 Spring启动示例:
Config config = new Config();
/* other hazelcast configs omittedfor brevity */
SerializerConfig kyroSerizlier = new SerializerConfig()
.setImplementation(new GlobalKryoSerializer())
.setTypeClass(Object.class);
config.getSerializationConfig().addSerializerConfig(kyroSerizlier);