能否在ComputeJob中访问模型类及反序列化IgniteCache值?
问题:ComputeJob中反序列化IgniteCache值遇到ClassNotFoundException,UriDeploymentSpi是否适用?
能否在ComputeJob中反序列化IgniteCache中的值?尝试操作时,我遇到了Marshaller相关的ClassNotFoundException。目前仅能通过使用BinaryObject(例如
IgniteCache<BinaryObject, BinaryObject>),或在Ignite节点上安装包含模型的jar包(需重启节点)来实现可靠反序列化。我希望将集群作为计算任务的通用资源池,以支持同一应用的多个版本使用该集群。由于每个应用实例会加载各自的数据,我并不希望在节点上安装单一版本的“模型实体”jar包。使用UriDeploymentSpi进行代码部署会是理想方案,请问这是否可行?或者我的Ignite使用方式不符合预期?
附ComputeJob代码:
public class FetchAtivoStatsNovoJob implements ComputeJob, IgniteCallable<Map<String, Integer>> { @IgniteInstanceResource private Ignite ignite; private List<Long> filterIds; private String ativosNovoCache; public FetchAtivoStatsNovoJob(List<Long> filterIds, String ativosNovoCache) { this.ativosNovoCache = ativosNovoCache; this.filterIds = filterIds; } @Override public Object execute() throws IgniteException { try { return call(); } catch (Exception e) { throw new IgniteException("Failed to fetch posts.", e); } } @Override public Map<String, Integer> call() throws Exception { IgniteCache<AtivoKeyNovo, AtivoNovo> cache = ignite.getOrCreateCache(ativosNovoCache); ScanQuery<AtivoKeyNovo, AtivoNovo> query = new ScanQuery<>(); query.setLocal(true); query.setFilter((k, ativo) -> filterIds.contains(k.getSubdominioId())); Map<String, Integer> result = new HashMap<String, Integer>(); try (QueryCursor<Cache.Entry<AtivoKeyNovo, AtivoNovo>> cursor = cache.query(query)) { for (Cache.Entry<AtivoKeyNovo, AtivoNovo> entry : cursor) { AtivoKeyNovo key = entry.getKey(); AtivoNovo value = entry.getValue(); // do some calculation, put on the result Map or insert a new record on another IgniteCache } } return result; } @Override public void cancel() { } }
回答
1. UriDeploymentSpi完全可行,匹配你的需求
UriDeploymentSpi正是为动态类部署场景设计的,能完美解决你不想在节点提前安装固定版本jar包的问题:
- 只需将包含
AtivoKeyNovo、AtivoNovo实体类以及ComputeJob的jar包,上传到所有集群节点可访问的URI路径(如共享文件目录、HTTP服务器) - 配置Ignite节点启用UriDeploymentSpi并指定上述URI,节点会自动拉取并加载对应类,无需重启
- 提交任务时,Ignite会自动处理类的分发与隔离,不同应用版本的类通过类加载器隔离,不会产生冲突,直接解决ClassNotFoundException问题
2. 其他可选方案
如果UriDeploymentSpi的配置成本较高,还可以考虑:
- Peer Class Loading机制:提交ComputeJob时,将实体类字节码随任务一同发送到节点,Ignite自动加载依赖类。需注意为不同应用版本配置独立的类加载器,避免类版本冲突。
- BinaryObject按需反序列化:继续使用
IgniteCache<BinaryObject, BinaryObject>,在需要业务逻辑处理时,通过binaryObject.deserialize()方法将其转换为具体实体类,无需提前部署类,但代码中需额外处理类型转换逻辑。
3. 代码调整建议
你的FetchAtivoStatsNovoJob代码本身没有问题,但需注意:
- 确保
AtivoKeyNovo和AtivoNovo实现Serializable接口,或更推荐的IgniteBinarylizable接口(序列化效率更高) - 如果使用UriDeploymentSpi,需确保jar包包含所有依赖类,且节点能正常拉取到该jar包
4. 你的Ignite使用方式符合设计目标
将集群作为通用计算资源池、支持多版本应用共享的思路,完全契合Ignite分布式计算+缓存的核心设计定位,不存在使用方式不符合预期的问题。
内容的提问来源于stack exchange,提问作者user19903
相关产品推荐
相关产品推荐

