jgroups - 需要解决两个主机组的 JGroups 非分组行为
问题描述
我正在使用 JGroups 通过让它们加入同名组来创建由两台机器组成的集群,并且我遇到了不稳定的分组行为,并且我在询问是否需要更改 JGroups 配置或服务器配置更改做使它工作。
当我在 JGroups 组中有两台主机,并且一名成员离开时,另一名成员在 viewAccepted 中会观察到这一点。但是当较早的成员返回时,他们都没有在 viewAccepted 函数中看到对方,并且他们在有效的独立组中运行(不好)。这种非分组行为可以是随机的。例如,我昨天下午 5 点断开连接后,今天早上重新启动了一个主机,但在组中都没有看到另一个主机。但是,一旦我停止了它们并重新启动,它们就在组中找到了彼此。
JGroups 的最终用途是将运行相同应用程序的两台 Tomcat 主机集群在一起,以便集群中列出的第一台主机运行报告,而第二台主机等待第一个主机死亡,然后取代第一台主机并运行报告。当第一台主机恢复服务时,它成为集群成员列表中的第二台,并等待另一台死亡。现在,应用程序的行为与下面的测试程序相呼应。
使用 JGroups jgroups-4.1.6.Final.jar 开箱即用,没有自定义 udp.xml 文件,也没有新 JChannel() 的参数。我有一个在两台 RHEL 7 主机上运行的测试应用程序,以使它们进入集群。下面的代码:
import java.util.List;
import org.jgroups.Address;
import org.jgroups.JChannel;
import org.jgroups.Message;
import org.jgroups.Receiver;
import org.jgroups.View;
public class ClusterTest implements Receiver {
private String clusterName;
private JChannel channel;
public ClusterTest(String[] args) {
if (args.length > 0) {
clusterName = args[0];
} else {
clusterName = "TEST_CLUSTER";
}
}
/**
* Joins the JGroups cluster
*/
private void joinCluster() {
System.out.println("joinCluster(): joining cluster \"" + clusterName + "\"");
try {
channel = new JChannel();
channel.setReceiver(this);
channel.connect(clusterName);
} catch (Exception e) {
System.out.print("joinCluster failed: ");
e.printStackTrace();
}
}
@Override
public void viewAccepted(View view) {
System.out.println("viewAccepted(): view = \"" + view + "\" for name = \"" + channel.getName() + "\" / \"" + channel.clusterName() + "\"");
List<Address> viewMembers = view.getMembers();
int memNum = 0;
for (Address member : viewMembers) {
System.out.println("viewAccepted(): member #" + memNum++ + " = " + member);
}
String myClusterName = channel.getName();
System.out.println("viewAccepted(): my clusterName = \"" + myClusterName + "\"");
if (viewMembers.size() > 0) {
String clusterActive = viewMembers.get(0).toString();
System.out.println("viewAccepted(): " + clusterName + ", cluster active = \"" + clusterActive + "\"\n");
}
}
@Override
public void receive(Message arg0) {
System.out.println("receive called, message = \"" + arg0 + "\"");
}
/**
* @param args
*/
public static void main(String[] args) {
ClusterTest tester = new ClusterTest(args);
tester.joinCluster();
}
}
我通过按 control-C 退出测试应用程序,所以这是一个不优雅的退出。
我们的 Linux 管理员查看了日志,没有发现任何异常。管理员还表示,没有任何限制或配置会阻止 UDP 流量。
我尝试过的事情:
- 根据此解决方案,增加多播的发送和接收缓冲区大小。由于缓冲区大小不足,我现在在启动时没有收到警告消息。
- 将 JGroups 版本更新到最新版本。
- 等待通宵尝试启动已停止的主机。
我不想尝试的事情:
- 使用 TCP,因为集群成员是流动的(它可以是任何两个主机),我宁愿在主机更改时不更新配置文件。
如果我无法让 JGroups 可靠地工作,我愿意接受替代解决方案。
谢谢!
解决方案
看起来您正在使用 JGroups 的默认 (udp.xml) 配置。为什么不复制 udp.xml(例如到您的主目录)并显式设置UDP.bind_addr
和设置UDP.mcast_addr
,然后将 udp.xml 传递给 JChannel 构造函数(new JChannel("/home/user/udp.xml")
)?
例如
<UDP bind_addr="site_local" mcast_addr="232.5.5.5".../>
运行后,您可以使用 probe 查看实际设置了哪些值:
probe.sh jmx=UDP.bind,mcast
推荐阅读
- vim - 原因:库版本不兼容
- sql - 同一查询中的嵌套存储过程 VS Exec 过程
- c++ - 此代码被转储并显示分段失败。我无法修复它
- flutter - 为什么在android中安装后应用程序覆盖?
- android - Flutter:我们检测到您的应用在您的 1 个或多个 app bundle 或 APK 的清单文件中包含 requestLegacyExternalStorage 标志
- carousel - Laravel 8中的轮播不工作只滑动一项
- javascript - 模块构建失败(来自 ./node_modules/babel-loader/lib/index.js):错误:插件/预设文件不允许导出对象,只有函数
- deployment - 如何将我网站的源代码部署到托管服务提供商
- git - 我们如何 `git stash apply` 在 repo 的所有状态之间移动?
- flutter - 类'未来
' 没有实例方法 '[]'。扑