首页 > 解决方案 > 需要解决两个主机组的 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 可靠地工作,我愿意接受替代解决方案。

谢谢!

标签: 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

推荐阅读