如何使 Ignite 像使用 TcpDiscoveryMulticastIpFinder 一样使用 TcpDiscoveryVmIpFinder 进行非阻塞行为?

Posted

技术标签:

【中文标题】如何使 Ignite 像使用 TcpDiscoveryMulticastIpFinder 一样使用 TcpDiscoveryVmIpFinder 进行非阻塞行为?【英文标题】:How to make Ignite act non-blocking with TcpDiscoveryVmIpFinder like it does with TcpDiscoveryMulticastIpFinder? 【发布时间】:2016-05-24 12:48:00 【问题描述】:

背景

我有一个基于 Spring 的 Web 应用程序。 在本地开发机器上,我有 2 个运行相同应用程序的 tomcat 实例 - 这样我测试网络场节点如何相互通信 我使用 Jelastic 云进行应用部署 在 Jelastic 上它不是作为网络农场运行,而是使用滚动更新机制(而 AppV1NodeA 运行并处理用户请求我启动 AppV2@NodeB,预热它并将用户请求重定向到它. 目标是让NodeBNodeA复制所有会话)

意图

当前发布版本使用基于 NodeJS 的第三个服务器作为节点间 MessageBus 的快捷方式。但最近我发现了 Ignite,并认为减少平台 (nodejs) 的数量并在 Java 中获取所有内容会很棒。 所以我用 Ignite 消息代替了基于 NodeJS 的消息。 Ignite 使用 Spring XML 配置和 org.apache.ignite.IgniteSpringBean 初始化 当使用TcpDiscoveryMulticastIpFinder 在本地运行我的应用程序时,它可以完美运行。即使没有 NodeB 启动,NodeA 也会启动。当我启动NodeB 时,它顺利加入集群,节点相互连接并完美通信。这里最重要的是我可以随时启动和停止节点,并且使用 Ignite 消息传递进行非阻塞无错误操作。

问题

但是在 Jelastic 上我没有多播,所以我必须明确定义 IP 地址列表(使用 TcpDiscoveryVmIpFinder),这没关系 - 我有每个节点的静态主机名。 但是现在当NodeA 启动时它会阻塞,直到它连接到NodeB。如果NodeB 不存在整个应用程序崩溃(部署失败)。

问题是 如何让它在场景中工作

    使用TcpDiscoveryVmIpFinder NodeA 启动(而NodeB 未启动) 期望:NodeA 可以正确运行任意时间(当然我不能向遥控器发送消息,因为没有连接遥控器 - 没关系) NodeB 随时开始 期望:NodeANodeB 找到彼此并相互通信(主要用于会话复制和其他消息) NodeA 停止 预期:NodeB 继续正常运行以服务用户请求 现在切换:NodeA 变为 NodeB,反之亦然;从第 3 步开始重复

【问题讨论】:

【参考方案1】:

您很可能错过了与TcpDiscoveryVmIpFinder 相关的一件重要事情。节点 A 和 B 都必须在 IP finder 的地址列表中包含它们自己的 IP 地址。这在本自述文件部分 [1] 中突出显示。 否则,您将陷入与节点 A 必须等待节点 B 加入集群时一样的情况。

为两个节点设置此 IP 查找器,一切都应按要求工作。

                <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">
                    <property name="addresses">
                        <list>
                            <value>hodeA_ip_address_or_host_name:47500..47509</value>
                            <value>hodeB_ip_address_or_host_name:47500..47509</value>
                        </list>
                    </property>
                </bean>

[1]https://apacheignite.readme.io/docs/cluster-config#static-ip-based-discovery

【讨论】:

【参考方案2】:

我找到了解决方法(不是解决方案)。如果您知道正确的解决方案 - 请在下面添加答案让我知道。

我将TcpDiscoverySpi 子类化并覆盖resolvedAddresses(),以测试候选人是否可以访问。

该解决方案并不完美,因为现在如果NodeA 没有找到NodeB,它将永远不会重试找到NodeB。然而,这并不是什么大问题,因为一旦NodeB 开始,它就会到达NodeA,并且他们开始互相交谈。滚动更新机制对我来说非常有效。

方法 isCandidateRespond 是一种快速且简单的解决方案,很可能会因情况而异。

这是一个代码sn-p:

public class TcpDiscoverySpiPrecheckingImpl extends TcpDiscoverySpi 
    private Logger log = Logger.getLogger(getClass());

    @Override
    protected Collection<InetSocketAddress> resolvedAddresses() throws IgniteSpiException 
        Collection<InetSocketAddress> candidates = super.resolvedAddresses();
        Collection<InetSocketAddress> approved = new ArrayList<>();
        for (InetSocketAddress candidate : candidates) 
            if (isCandidateRespond(candidate)) 
                approved.add(candidate);
            
        
        return approved;
    

    private boolean isCandidateRespond(InetSocketAddress candidate) 
        if (log.isTraceEnabled()) 
            log.trace("Checking if remote node responds: " + candidate);
        
        URL url = null;
        try 
            url = new URL("http://" + candidate.getHostName() + "/");
            try (InputStream stream = url.openStream()) 
                return true;
            
         catch (Throwable t) 
            log.info("Candidate remote node didn't respond: " + url + ". Reason: " + t.getMessage());
            return false;
        
    

【讨论】:

以上是关于如何使 Ignite 像使用 TcpDiscoveryMulticastIpFinder 一样使用 TcpDiscoveryVmIpFinder 进行非阻塞行为?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Apache Ignite.NET 瘦客户端连接到特定网格

Hazelcast 是不是支持像 Apache Ignite 这样的 SQL 查询?

使用 TcpDiscoveryKubernetesIpFinder 在 Kubernetes 集群中无法发现 Ignite

在 YARN 上使用 Ignite 确保本地缓存

安排任务以将 BigQuery 表加载到 Apache Ignite

Java/Ignite - Try 块的功能 [重复]