Apache Ignite多Docker节点Compute Broadcast执行异常排查求助
Apache Ignite Docker集群Compute Broadcast故障排查与修复示例
问题描述
我正在试用Apache Ignite,发现其文档存在不完善之处。使用2.14.0-arm64版本的Docker镜像搭建两节点集群,已为两个Ignite容器暴露全部端口,但Compute Broadcast仅在使用默认端口的节点上生效,无法在另一个容器执行。Ignite客户端能发现两个节点,但计算任务仅在保留默认端口映射的容器上触发,同时出现“无法向ignite-node2节点ID发送消息”的错误提示。
注:Docker配置正常,容器间网桥网络正常,服务器日志显示存在2个服务器节点、0个客户端节点。
当前节点启动命令
- 第一个节点(可正常执行任务):
docker run --name ignite-node1 \ -p 47500:47500 -p 47100:47100 \ -d apacheignite/ignite:2.14.0-arm64
- 第二个节点(无法执行任务):
docker run --name ignite-node2 \ -p 47501:47500 -p 47101:47100 \ -d apacheignite/ignite:2.14.0-arm64
使用的原示例代码
public class HelloWorld { public static void main(String[] args) throws IgniteException { // 准备IgniteConfiguration配置 IgniteConfiguration cfg = new IgniteConfiguration(); // 将节点设置为客户端模式 cfg.setClientMode(true); // 设置IP Finder确保客户端能找到服务器节点 TcpDiscoveryMulticastIpFinder ipFinder = new TcpDiscoveryMulticastIpFinder(); ipFinder.setAddresses(Collections.singletonList("127.0.0.1:47500..47509")); cfg.setDiscoverySpi(new TcpDiscoverySpi().setIpFinder(ipFinder)); // 启动节点 Ignite ignite = Ignition.start(cfg); // 创建缓存并插入数据 IgniteCache<Integer, String> cache = ignite.getOrCreateCache("myCache"); cache.put(1, "Hello"); cache.put(2, "World!"); System.out.println(">> 创建缓存并添加数据完成。"); // 在服务器节点上执行自定义计算任务 ignite.compute(ignite.cluster().forServers()).broadcast(new RemoteTask()); System.out.println(">> 计算任务已提交,请查看服务器节点输出。"); // 断开集群连接 ignite.close(); } /** * 打印节点ID、OS和JRE信息的计算任务,同时演示从任务中访问缓存数据 */ private static class RemoteTask implements IgniteRunnable { @IgniteInstanceResource Ignite ignite; @Override public void run() { System.out.println(">> 正在执行计算任务"); System.out.println( " 节点ID: " + ignite.cluster().localNode().id() + "\n" + " 操作系统: " + System.getProperty("os.name") + " Java运行环境: " + System.getProperty("java.runtime.name")); IgniteCache<Integer, String> cache = ignite.cache("myCache"); System.out.println(">> " + cache.get(1) + " " + cache.get(2)); } } }
排查方向
- 端口映射地址不匹配:Docker端口映射后,Ignite节点默认向集群报告容器内部端口,而非宿主机映射端口,导致其他节点/客户端无法正确路由到该节点。
- 节点地址配置缺失:Docker环境下需显式配置Ignite节点对外暴露的地址(宿主机IP+映射端口),否则集群内节点无法识别彼此的外部访问路径。
- 通信SPI端口未同步:Ignite的
TcpCommunicationSpi默认使用47100端口,同样需要确保节点对外暴露的通信端口配置正确。
修复方案与可用Compute HelloWorld示例
步骤1:修改Docker启动命令,配置节点外部地址
启动节点时通过环境变量指定节点的发现地址和通信地址,让集群内节点知晓彼此的外部访问路径:
- 启动ignite-node1:
docker run --name ignite-node1 \ -p 47500:47500 -p 47100:47100 \ -e "IGNITE_JVM_OPTS=-DIGNITE_TCP_DISCOVERY_ADDRESS=127.0.0.1:47500 -DIGNITE_TCP_COMMUNICATION_ADDRESS=127.0.0.1:47100" \ -d apacheignite/ignite:2.14.0-arm64
- 启动ignite-node2:
docker run --name ignite-node2 \ -p 47501:47500 -p 47101:47100 \ -e "IGNITE_JVM_OPTS=-DIGNITE_TCP_DISCOVERY_ADDRESS=127.0.0.1:47501 -DIGNITE_TCP_COMMUNICATION_ADDRESS=127.0.0.1:47101" \ -d apacheignite/ignite:2.14.0-arm64
步骤2:修改客户端代码,指定所有节点的映射端口
更新客户端IP Finder配置,明确列出两个节点的宿主机地址和映射端口:
TcpDiscoveryMulticastIpFinder ipFinder = new TcpDiscoveryMulticastIpFinder(); ipFinder.setAddresses(Arrays.asList("127.0.0.1:47500", "127.0.0.1:47501")); cfg.setDiscoverySpi(new TcpDiscoverySpi().setIpFinder(ipFinder));
完整修复后的HelloWorld代码
import org.apache.ignite.Ignite; import org.apache.ignite.IgniteCache; import org.apache.ignite.IgniteException; import org.apache.ignite.Ignition; import org.apache.ignite.cluster.ClusterGroup; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.lang.IgniteRunnable; import org.apache.ignite.resources.IgniteInstanceResource; import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi; import org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder; import java.util.Arrays; public class HelloWorld { public static void main(String[] args) throws IgniteException { // 准备IgniteConfiguration配置 IgniteConfiguration cfg = new IgniteConfiguration(); // 将节点设置为客户端模式 cfg.setClientMode(true); // 设置IP Finder,指定所有服务器节点的宿主机地址和映射端口 TcpDiscoveryMulticastIpFinder ipFinder = new TcpDiscoveryMulticastIpFinder(); ipFinder.setAddresses(Arrays.asList("127.0.0.1:47500", "127.0.0.1:47501")); cfg.setDiscoverySpi(new TcpDiscoverySpi().setIpFinder(ipFinder)); // 启动客户端节点 Ignite ignite = Ignition.start(cfg); // 创建缓存并插入数据 IgniteCache<Integer, String> cache = ignite.getOrCreateCache("myCache"); cache.put(1, "Hello"); cache.put(2, "World!"); System.out.println(">> 创建缓存并添加数据完成。"); // 获取所有服务器节点集群组,广播执行任务 ClusterGroup serverGroup = ignite.cluster().forServers(); ignite.compute(serverGroup).broadcast(new RemoteTask()); System.out.println(">> 计算任务已提交,请查看两个服务器节点的控制台输出。"); // 断开集群连接 ignite.close(); } /** * 自定义计算任务:打印节点信息并访问缓存 */ private static class RemoteTask implements IgniteRunnable { @IgniteInstanceResource private Ignite ignite; @Override public void run() { System.out.println(">> 正在执行计算任务"); System.out.println(" 节点ID: " + ignite.cluster().localNode().id()); System.out.println(" 操作系统: " + System.getProperty("os.name")); System.out.println(" Java运行环境: " + System.getProperty("java.runtime.name")); // 访问缓存数据 IgniteCache<Integer, String> cache = ignite.cache("myCache"); System.out.println(">> 缓存数据: " + cache.get(1) + " " + cache.get(2)); } } }
验证方法
- 启动两个节点后,查看节点日志确认集群正常组建(日志包含
All nodes topology snapshot且显示两个节点) - 运行客户端代码,分别查看两个容器的日志:
两个节点均会输出计算任务的执行日志。docker logs ignite-node1 docker logs ignite-node2
内容的提问来源于stack exchange,提问作者JUser
相关产品推荐
相关产品推荐

