Ignite零部署是如何工作的

3

Ignite拥有一项非常出色的"零部署"功能,其工作流程如下:

  1. Ignite将检查本地类路径上是否有该类(即在系统启动时加载),如果有,则返回该类。在这种情况下,不会从对等节点加载任何类。
  2. 如果本地没有可用的类,则会向原始节点发送请求以提供类定义。原始节点将发送类字节码定义,然后在工作节点上加载类。这只会发生一次 - 一旦类定义在节点上加载,就不必再次加载。

另外,我写了一个示例代码:

Collection<Long> broadcastResult = compute.broadcast(new IgniteCallable<Long>() {
                @Override
                public Long call() throws Exception {
                    long result = 0;
                    Long total = getTotal(10);
                    for (int i = 0; i < total; i++) {
                        LOGGER.info("adding {}, result {}", i, (result = result + i));
                    }
                    return result;
                }
            });
...
    public static Long getTotal(long total) {
            LOGGER.info("Total:{}", total);
            return total;
        }

它可以正常工作,远程节点打印了add xxx日志十次。但我真的很想知道是怎么做到的?

  1. Ignite如何知道My IgniteCallable Instance需要getTotal(long total)方法?
  2. 当我只给它My IgniteCallable Instance's Reference而不是一个类文件时,Ignite如何将My IgniteCallable Instance's Byte Code传输到远程节点?

请帮帮我,谢谢!

1个回答

0

回答你的问题。

  1. 最初,您的IgniteCallable会被序列化并通过网络发送。当JVM开始执行它并在需要getTotal时到达该点时,它将查找具有此方法的类定义,如果JVM在本地找不到它,它也将从原始节点预加载它。

  2. 一切都很简单。基本上,我们只需使用像igniteCalllable.getClass()这样的调用获取您实例的Class,对其进行序列化并通过网络发送。如果您查看Class对象源代码,您将看到它是可序列化的。


小修正。getTotal方法是静态的,所以封闭类的实例不会被序列化(甚至可能不存在)。但是当服务器节点需要时,该类的字节码将由服务器节点的类加载器加载。 - Valentin Kulichenko
谢谢回答。我已经理解了一些要点,但还不是很清楚。当一个节点发送IgniteCallable实例到远程节点执行时,它通常会被序列化。关键点在于远程节点有一个特殊的类加载器,在反序列化过程中,类加载器的resolve()方法将被调用,并且所有依赖的类都将被传递给类加载器,类加载器将尝试从本地加载类,如果本地有,则直接加载,否则将广播一个Class Fetch请求并从其他节点获取。但我还不是完全确定或清楚。 - BilboDai
你的理解几乎是完全正确的。我唯一要补充的是,一个依赖类,其方法或实例在你的IgniteCallable源代码中被使用时,将只会在JVM执行到需要该依赖类的地方时才会被加载。 - dmagda
谢谢,@dmagda。我已经查看了ignite项目代码,但是我没有找到任何关于Classloader工作的详细信息。 - BilboDai
就这样了!非常感谢! - BilboDai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接