如何配置Vert.x事件总线以使其在Docker容器集群中工作?

6
在我的当前设置中,我正在使用Hazelcast群集管理器的默认组播选项。当我通过Docker网络链接连接我的容器化Vertx模块的实例时,我可以看到它们成功地创建了Hazelcast群集。然而,当我尝试从一个模块上的事件总线发布事件时,另一个模块没有反应。我不确定Hazelcast群集中的网络设置与事件总线的网络设置有何关联。
目前,我对每个Vert.x模块都有以下编程配置,每个模块都部署在一个Docker容器中。
ClusterManager clusterManager = new HazelcastClusterManager();
VertxOptions vertxOptions = new VertxOptions()
            .setClustered(true)
            .setClusterManager(clusterManager);
vertxOptions.setEventBusOptions(new EventBusOptions()
            .setClustered(true)
            .setClusterPublicHost("application"));

Vert.x Core手册指出,我可能需要为事件总线配置clusterPublicHostclusterPublicPort,但我不确定它们如何与一般的网络拓扑相关。

3个回答

10
一个答案在这里: https://groups.google.com/d/msg/vertx/_2MzDDowMBM/nFoI_k6GAgAJ 很多人在文档中(包括我自己)都忽略了一个问题:事件总线没有使用集群管理器来发送事件总线消息。也就是说,在您的示例中使用Hazelcast作为集群管理器,您已经成功启动和通信Hazelcast集群(因此您的集群管理器没问题),但是事件总线未能与其他docker实例通信,可能由于以下原因之一:
1. 它试图使用不正确的IP地址连接到其他节点(即Docker实例上的私有接口IP而非公共映射的IP) 2. 它试图在Docker未配置转发的端口上进行通信(如果没有指定端口,则事件总线会选择一个动态端口)
你需要做的事情是: 1. 告诉Vertx每个实例应该使用什么IP地址来与其他节点通信(使用“-cluster-host” [命令行],“setClusterPublicHost”[VertXOptions] 或 “vertx.cluster.public.host” [系统属性]选项) 2. 显式告诉Vertx要使用的事件总线通信端口,并确保Docker正在转发这些端口的流量(使用“vertx.cluster.public.port” [系统属性],“setClusterPublicPort”[VertXOptions] 或“-cluster-port” [命令行]选项)。我过去一直使用的是15701,因为它很容易记住(只需要在Hazelcast端口前加上一个'1')。
事件总线仅使用集群管理器来管理其他Vertx实例的IP /端口信息和注册。消费者/生产者。通信是独立于群集管理器进行的,这就是为什么您可以正确配置和通信群集管理器,但仍然没有事件总线通信的原因。

如果两个容器都在同一主机上运行,则可能不需要执行上述两个步骤,但一旦您开始在不同的主机上运行它们,就绝对需要执行这两个步骤。

还可能发生的另一件事情是,当未指定vert.x(而不是hazelcast)用于通过eventbus进行通信的IP时,vert.x使用回环接口。问题在于,您不知道使用哪个接口进行通信(回环、带IP的接口,甚至可能有多个带IP的接口)。

为了解决这个问题,我曾经编写了一个方法 https://github.com/swisspush/vertx-cluster-watchdog/blob/master/src/main/java/org/swisspush/vertx/cluster/ClusterWatchdogRunner.java#L101


3
集群管理器工作正常,集群管理器配置在集群中的每个节点(机器/ Docker容器)上必须相同,或者根本不进行任何配置(使用集群管理器的默认配置)。

您必须使事件总线配置在每个节点上保持一致,并将每个节点的集群主机设置为该节点本身的IP地址和任意端口号(除非您尝试在同一节点上运行多个Vert.x实例,否则必须为每个Vert.x实例选择不同的端口号)。

例如,如果节点的IP地址是192.168.1.12,则应执行以下操作:
VertxOptions options = new VertxOptions()
                .setClustered(true)
                .setClusterHost("192.168.1.12") // node ip
                .setClusterPort(17001) // any arbitrary port but make sure no other Vert.x instances using same port on the same node
                .setClusterManager(clusterManager);

如果您想在另一个IP地址为192.168.1.56的节点上执行此操作,则需要执行以下步骤:

VertxOptions options = new VertxOptions()
                .setClustered(true)
                .setClusterHost("192.168.1.56") // other node ip
                .setClusterPort(17001) // it is ok because this is a different node
                .setClusterManager(clusterManager);

2
发现了这个解决方案,对我非常有效。以下是我的代码片段(重要部分是options.setClusterHost())。
public class Runner {

    public static void run(Class clazz) {
        VertxOptions options = new VertxOptions();
        try {
            // for docker binding
            String local = InetAddress.getLocalHost().getHostAddress();
            options.setClusterHost(local);
        } catch (UnknownHostException e) { }

        options.setClustered(true);

        Vertx.clusteredVertx(options, res -> {
            if (res.succeeded()) {
                res.result().deployVerticle(clazz.getName());
            } else {
                res.cause().printStackTrace();
            }
        });
    }
}

public class Publisher extends AbstractVerticle {

    public static void main(String[] args) {
        Runner.run(Publisher.class);
    }

    ...
}

不需要定义其他东西...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接