如何使 Ignite 像使用 TcpDiscoveryMulticastIpFinder 一样使用 TcpDiscoveryVmIpFinder 进行非阻塞操作?
How to make Ignite act non-blocking with TcpDiscoveryVmIpFinder like it does with TcpDiscoveryMulticastIpFinder?
背景:
- 我有一个基于 spring 的网络应用程序。
- 在本地开发机器上,我有 2 个 tomcat 运行相同应用程序的实例 - 这样我就可以测试网络场节点如何相互通信
- 我使用 Jelastic 云进行应用程序部署
- 在 Jelastic 上它不是 运行 作为网络农场,而是使用滚动更新机制(而
AppV1
在 NodeA
处是 运行 并且处理用户请求我启动 AppV2@NodeB
,预热并将用户请求重定向到它。目标是让 NodeB
从 NodeA
) 复制所有会话
意向
- 当前版本使用基于 NodeJS 的第三个服务器作为节点之间 MessageBus 的快捷方式。但最近我发现了 Ignite 并认为减少平台 (nodejs) 的数量并获得 Java.
中的所有内容会很棒
- 所以我用 Ignite 消息替换了基于 NodeJS 的消息。使用 Spring XML 配置和
org.apache.ignite.IgniteSpringBean
初始化 Ignite
- 当 运行 我的应用程序在本地使用
TcpDiscoveryMulticastIpFinder
时,它可以完美运行。即使没有 NodeB
启动,NodeA
也会启动。当我开始 NodeB
时,它顺利加入集群,节点相互连接并完美通信。这里最重要的是我可以随时启动和停止节点,并且我使用 Ignite 消息传递进行非阻塞无错误操作。
问题
- 但是在 Jelastic 上我没有多播,所以我必须明确定义 IP 地址列表(使用
TcpDiscoveryVmIpFinder
),这没关系 - 我有每个节点的静态主机名。 但是 现在当 NodeA
启动时它会阻塞,直到它连接到 NodeB
。如果 NodeB
不存在整个应用程序崩溃(部署失败)。
问题是
如何让它在场景中工作
TcpDiscoveryVmIpFinder
已使用
NodeA
启动(而 NodeB
未启动)
- 期望:
NodeA
可以正确运行任何时间(当然我不能向遥控器发送消息,因为没有连接遥控器 - 没关系)
- 随时
NodeB
开始
- 预期:
NodeA
和 NodeB
找到彼此并相互通信(主要用于会话复制和其他消息)
NodeA
已停止
- 预期:
NodeB
继续正常服务于用户请求
- 现在切换:
NodeA
变为 NodeB
,反之亦然;从第 3 步开始重复
我找到了解决方法(不是解决方案)。如果您知道正确的解决方案 - 请在下面添加答案让我知道。
我将 TcpDiscoverySpi
子类化并覆盖 resolvedAddresses()
以测试候选人是否可以联系到他们。
该解决方案并不完美,因为现在如果 NodeA
没有找到 NodeB
,它将永远不会重试寻找 NodeB
。然而,这并不是一个阻碍,因为一旦 NodeB
开始,它就会到达 NodeA
并且他们开始互相交谈。如此有效的滚动更新机制对我有用。
方法 isCandidateRespond
是快速的解决方案,很可能会因情况而异。
这是一个代码片段:
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;
}
}
}
很可能您错过了一件与 TcpDiscoveryVmIpFinder
相关的重要事情。节点 A 和 B 都必须在 IP 查找器的地址列表中包含自己的 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
背景:
- 我有一个基于 spring 的网络应用程序。
- 在本地开发机器上,我有 2 个 tomcat 运行相同应用程序的实例 - 这样我就可以测试网络场节点如何相互通信
- 我使用 Jelastic 云进行应用程序部署
- 在 Jelastic 上它不是 运行 作为网络农场,而是使用滚动更新机制(而
AppV1
在NodeA
处是 运行 并且处理用户请求我启动AppV2@NodeB
,预热并将用户请求重定向到它。目标是让NodeB
从NodeA
) 复制所有会话
意向
- 当前版本使用基于 NodeJS 的第三个服务器作为节点之间 MessageBus 的快捷方式。但最近我发现了 Ignite 并认为减少平台 (nodejs) 的数量并获得 Java. 中的所有内容会很棒
- 所以我用 Ignite 消息替换了基于 NodeJS 的消息。使用 Spring XML 配置和
org.apache.ignite.IgniteSpringBean
初始化 Ignite
- 当 运行 我的应用程序在本地使用
TcpDiscoveryMulticastIpFinder
时,它可以完美运行。即使没有NodeB
启动,NodeA
也会启动。当我开始NodeB
时,它顺利加入集群,节点相互连接并完美通信。这里最重要的是我可以随时启动和停止节点,并且我使用 Ignite 消息传递进行非阻塞无错误操作。
问题
- 但是在 Jelastic 上我没有多播,所以我必须明确定义 IP 地址列表(使用
TcpDiscoveryVmIpFinder
),这没关系 - 我有每个节点的静态主机名。 但是 现在当NodeA
启动时它会阻塞,直到它连接到NodeB
。如果NodeB
不存在整个应用程序崩溃(部署失败)。
问题是 如何让它在场景中工作
TcpDiscoveryVmIpFinder
已使用NodeA
启动(而NodeB
未启动)- 期望:
NodeA
可以正确运行任何时间(当然我不能向遥控器发送消息,因为没有连接遥控器 - 没关系) - 随时
NodeB
开始 - 预期:
NodeA
和NodeB
找到彼此并相互通信(主要用于会话复制和其他消息) NodeA
已停止- 预期:
NodeB
继续正常服务于用户请求 - 现在切换:
NodeA
变为NodeB
,反之亦然;从第 3 步开始重复
我找到了解决方法(不是解决方案)。如果您知道正确的解决方案 - 请在下面添加答案让我知道。
我将 TcpDiscoverySpi
子类化并覆盖 resolvedAddresses()
以测试候选人是否可以联系到他们。
该解决方案并不完美,因为现在如果 NodeA
没有找到 NodeB
,它将永远不会重试寻找 NodeB
。然而,这并不是一个阻碍,因为一旦 NodeB
开始,它就会到达 NodeA
并且他们开始互相交谈。如此有效的滚动更新机制对我有用。
方法 isCandidateRespond
是快速的解决方案,很可能会因情况而异。
这是一个代码片段:
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;
}
}
}
很可能您错过了一件与 TcpDiscoveryVmIpFinder
相关的重要事情。节点 A 和 B 都必须在 IP 查找器的地址列表中包含自己的 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