需要解决双主机组的 JGroups 非分组行为

Need to solve JGroups non-grouping behavior for a two-host group

我正在使用 JGroups 通过让两台机器加入同名组来创建一个集群,但我的分组行为不稳定,我想问是否有 JGroups 配置更改或我需要更改服务器配置才能使其正常工作。

当我在 JGroups 组中有两个主机时,一个成员离开,另一个成员在 viewAccepted 中观察到这一点。但是当较早的成员 returns 时,他们在 viewAccepted 函数中都看不到对方,并且他们 运行 在有效独立的组中(不好)。这种非分组行为可以是随机的。比如我昨天下午5点断开了一台主机,今天早上重启了一台主机,群里都没看到另一台。然而,一旦我停止他们两个并重新启动,他们在组中找到了对方。

JGroups 的最终用途是将两个 Tomcat 主机 运行 连接到同一个应用程序,这样集群中列出的第一台主机 运行s 报告,而第二台等待第一个死去,然后接替第一个宿主的位置和 运行 的报告。当第一台主机恢复服务时,它成为集群成员列表中的第二台,并等待另一台主机死亡。现在应用程序的行为与下面的测试程序的行为相呼应。

使用开箱即用的 JGroups jgroups-4.1.6.Final.jar,没有自定义 udp.xml 文件,也没有新 JChannel() 的参数。我有一个测试应用程序 运行s 在两个 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 的默认 (udp.xml) 配置。为什么不复制 udp.xml(例如到您的主目录)并显式设置 UDP.bind_addrUDP.mcast_addr,然后将 udp.xml 传递给 JChannel 构造函数(new JChannel("/home/user/udp.xml"))?

例如

<UDP bind_addr="site_local" mcast_addr="232.5.5.5".../>

运行后,您可以使用探针查看实际设置了哪些值:

probe.sh jmx=UDP.bind,mcast

(回答我自己的问题)尽管我说我不想,但我还是继续使用 TCP,但我有点绝望,而且软件交付晚了。我没有看到我在 UDP 上看到的不良行为,其中包括主机无限期地相互忽略的外观。我修改了 vanilla TCP 配置文件以获得所需的性能。

我不打算采用 UDP 解决方案,因为我还有其他工作要做,而且 TCP 解决方案似乎足以投入生产。