【问题标题】:How does peer classloading work in Apache Ignite?对等类加载在 Apache Ignite 中是如何工作的?
【发布时间】:2026-02-12 18:55:02
【问题描述】:

我目前正在研究我们的项目在高负载下出现的以下问题:

class org.apache.ignite.IgniteDeploymentException: Failed to deploy user message: java.nio.HeapByteBuffer[pos=0 lim=180 cap=180]
at org.apache.ignite.internal.util.IgniteUtils$8.apply(IgniteUtils.java:825)
at org.apache.ignite.internal.util.IgniteUtils$8.apply(IgniteUtils.java:823)
at org.apache.ignite.internal.util.IgniteUtils.convertException(IgniteUtils.java:944)
at org.apache.ignite.internal.IgniteMessagingImpl.send0(IgniteMessagingImpl.java:106)
at org.apache.ignite.internal.IgniteMessagingImpl.send(IgniteMessagingImpl.java:82)
...

Caused by: class org.apache.ignite.internal.IgniteDeploymentCheckedException: Failed to deploy user message: java.nio.HeapByteBuffer[pos=0 lim=180 cap=180]
at org.apache.ignite.internal.managers.communication.GridIoManager.sendUserMessage(GridIoManager.java:1571)
at org.apache.ignite.internal.IgniteMessagingImpl.send0(IgniteMessagingImpl.java:103)
... 25 more

简而言之,情况如下:

  • 三个节点上的分布式缓存,所有节点在一个工作站上运行(在此测试中);
  • 每个节点上的工人;
  • worker 之间的消息传递是使用 IgniteMessaging 完成的(主题的类型为 String,我已尝试将 byte[] 和 ByteBuffer 作为消息类);
  • 客户端连接到集群并触发一些业务逻辑,这会导致跨节点消息传递和扫描查询。查询和消息传递同时执行。

我们在持续部署模式下使用对等类加载(问题与共享模式相同)。根据 Ignite 文档,只有在版本发生更改时才应重新部署类,但它似乎不起作用。

我注意到日志中有很多类似的消息:

2017-05-05 13:31:28 INFO   org.apache.ignite.logger.java.JavaLogger info Removed undeployed class: GridDeployment [ts=1493980288578, depMode=CONTINUOUS, clsLdr=WebAppClassLoader=MyApp@38815daa, clsLdrId=36c3828db51-0d65e7d5-77bf-444d-9b8b-d18bde94ad13, userVer=0, loc=true, sampleClsName=java.lang.String, pendingUndeploy=false, undeployed=true, usage=0]
...
2017-05-05 13:31:29 INFO   org.apache.ignite.logger.java.JavaLogger info Removed undeployed class: GridDeployment [ts=1493980289125, depMode=CONTINUOUS, clsLdr=WebAppClassLoader=MyApp@355f6680, clsLdrId=1dd3828db51-1b20df7a-a98d-45a3-8ab6-e5d229945830, userVer=0, loc=true, sampleClsName=java.lang.String, pendingUndeploy=false, undeployed=true, usage=0]
...

这是我使用 ByteBuffer 作为消息类型的时候。在 byte[] 的情况下,B[ 类正在不断地重新部署。

我已经对 Ignite 内核进行了一些分析,并怀疑当类加载器中的至少一个类在其他加载器中重新部署时,会为类加载器中的所有类触发取消部署。

它发生在 org.apache.ignite.spi.deployment.local.LocalDeploymentSpi#register

  • 首先,我们得到一个“为注册类添加的新资源的映射” loader”使用 LocalDeploymentSpi#addResource。
  • 然后我们“删除除 {@code ignoreClsLdr} 之外的所有类加载器的资源。”使用 LocalDeploymentSpi#removeResources。在这个方法中,看起来我们将所有包含旧版本新资源的加载器添加到“注定”的集合中。
  • 最后,我们迭代这个集合并为每个元素调用 onClassLoaderReleased。后一个操作实际上会导致所有类都被取消部署(最终导致“Removed undeployed class”消息)。

我不明白这个概念。为什么有多个类加载器?为什么在这种情况下我们要取消部署整个类加载器?

如果有人能解释一下,Ignite 中的对等类加载是如何“在后台”工作的,我将不胜感激。

附:我正在查看 Ignite 2.1.0 新快照的来源,但其行为与标准 Ignite 1.9.0 相同。

【问题讨论】:

    标签: ignite


    【解决方案1】:

    【讨论】: