Infinispan集群重启报MarshallableUserObject marshaller未覆盖问题求助
问题根因
你遇到的异常是Infinispan 12.x版本序列化机制导致的:Infinispan从10.x开始默认使用Protostream作为序列化框架,自定义缓存值对象仅实现Serializable接口不足以被持久化层正确反序列化。当节点重启触发缓存重平衡时,需要从RocksDB读取全量持久化数据进行反序列化传输,未注册的实体类会触发MarshallableUserObject marshaller not overridden in SerializationContext异常,导致状态传输失败、节点卡住。
解决方案
1. 为自定义实体配置Protostream序列化(推荐生产使用)
给IndexedEndpointEventModel添加Protostream序列化注解,示例如下:
import org.infinispan.protostream.annotations.ProtoFactory; import org.infinispan.protostream.annotations.ProtoField; import org.hibernate.search.mapper.pojo.mapping.definition.annotation.Indexed; import org.hibernate.search.mapper.pojo.mapping.definition.annotation.GenericField; @Indexed public class IndexedEndpointEventModel implements Serializable { // 字段省略 // 无参构造加@ProtoFactory注解 @ProtoFactory public IndexedEndpointEventModel() { // 原有初始化逻辑 } // 每个字段对应添加@ProtoField注解,number序号唯一不重复 @ProtoField(number = 1) public String getField1() { return field1; } @ProtoField(number = 2) public LocalDateTime getField2() { return field2; } // 其余字段依次按顺序添加@ProtoField注解,注意number不能重复 // 其余getter/setter省略 }
然后配置类路径下的META-INF/services/org.infinispan.protostream.SerializationContextInitializer文件,内容为自动生成的初始化器全类名(使用Protostream注解处理器会自动生成该实现类,也可手动实现接口注册实体规则)。
2. 全局配置加载序列化初始化器
嵌入式场景的Java配置示例:
GlobalConfiguration globalConfig = new GlobalConfigurationBuilder() .serialization() // 注册你自定义的序列化初始化器 .addContextInitializer(new IndexedEndpointEventModelContextInitializerImpl()) .build();
XML配置示例:
<serialization> <context-initializer class="org.example.model.IndexedEndpointEventModelContextInitializerImpl"/> </serialization>
3. 临时规避方案
如果需要快速验证问题,可以临时降级使用JDK序列化,配置如下:
GlobalConfiguration globalConfig = new GlobalConfigurationBuilder() .serialization() .marshaller(new JavaSerializationMarshaller()) .allowList() .addClasses(IndexedEndpointEventModel.class) .build();
注意该方案序列化性能低、跨版本兼容性差,仅推荐测试验证使用,不建议生产环境部署。
注意事项
修改序列化配置后,需要清空之前RocksDB持久化目录下的所有旧数据,避免旧格式的残留数据再次触发反序列化异常。
内容的提问来源于stack exchange,提问作者iamundef
相关产品推荐
相关产品推荐

