如果手动创建vert.x实例,则群集Vert.x在docker中不起作用

时间:2018-03-03 14:06:34

标签: docker vert.x

我设置了一个小项目,用于在集群环境中学习Vert.x的功能,但是当我尝试在Docker镜像中创建vertx实例时,我遇到了一些奇怪的问题。

该项目仅包含2个Verticle,它们部署在不同的Docker容器中,并使用事件总线相互通信

如果我使用vertx提供的启动器:

    Launcher.executeCommand("run", verticleClass, "--cluster")

(或者只是声明主要类是io.vertx.core.Launcher并且放置正确的参数)

一切都适用于本地和内部泊坞窗图像。但是,如果我尝试使用

手动创建vertx实例
Vertx.rxClusteredVertx(VertxOptions())
        .flatMap { it.rxDeployVerticle(verticleClass) }
        .subscribe()

然后它没有在Docker中工作(它在本地工作)。或者,更直观地

|                   | Local     | Docker    |
|:---------------:  |:-----:    |:------:   |
|  Vertx launcher   |   Y       |    Y      |
| Custom launcher   |   Y       |    N      |

通过检查Docker日志,似乎一切正常。我可以看到两个垂直相互认识:

Members [2] {
    Member [172.18.0.2]:5701 - c5e9636d-b3cd-4e24-a8ce-e881218bf3ce
    Member [172.18.0.3]:5701 - a09ce83d-e0b3-48eb-aad7-fbd818c389bc this
}

但是当我尝试通过事件总线发送消息时,会抛出以下异常:

WARNING: Connecting to server localhost:33845 failed
io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: localhost/127.0.0.1:33845
    at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
    at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:717)
    at io.netty.channel.socket.nio.NioSocketChannel.doFinishConnect(NioSocketChannel.java:325)
    at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:340)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:633)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:580)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:497)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:459)
    at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:886)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.net.ConnectException: Connection refused
    ... 11 more

为了简化我上传项目to Github的内容。我试着让它变得尽可能简单,所以它有2个Verticle&每个组合有2个主要类和大量脚本

2 个答案:

答案 0 :(得分:0)

  

通过检查Docker日志,似乎一切正常。我可以看到   两个Verticle彼此都知道

是的,因为您的集群管理器工作正常,但您还应该在集群中的每个节点(计算机/ docker容器)中使事件总线配置保持一致,因为Vert.x文档中提到:集群管理器不处理事件总线节点间传输,这由Vert.x直接通过TCP连接完成。

您必须将每个节点上的群集主机设置为此节点本身的IP地址和任意端口号(除非您尝试在同一节点上运行多于Vert.x实例,否则必须为每个节点选择不同的端口号Vert.x实例)。您遇到的错误是因为默认群集主机是local host

例如,如果节点的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);

答案 1 :(得分:0)

通过对Vert.X Launcher代码进行更多研究,我发现在内部它做的不仅仅是“解析”输入

如果vertx配置为在群集模式下运行,Launcher正在设置群集地址本身(通过BareCommand类),以便使用您自己的Launcher行为复制Main行为{1}}类(并且可以通过代码而不是通过args灵活配置vertx实例)代码如下:

fun main(args: Array<String>) {

    Vertx.rxClusteredVertx(
            VertxOptions(
                    clusterHost = getDefaultAddress()
            )
    )
            .flatMap { it.rxDeployVerticle(verticleClass) }
            .subscribe()
}


// As taken from io.vertx.core.impl.launcher.commands.BareCommand
fun getDefaultAddress(): String? {
    val nets: Enumeration<NetworkInterface>
    try {
        nets = NetworkInterface.getNetworkInterfaces()
    } catch (e: SocketException) {
        return null
    }

    var netinf: NetworkInterface
    while (nets.hasMoreElements()) {
        netinf = nets.nextElement()

        val addresses = netinf.inetAddresses

        while (addresses.hasMoreElements()) {
            val address = addresses.nextElement()
            if (!address.isAnyLocalAddress && !address.isMulticastAddress
                    && address !is Inet6Address) {
                return address.hostAddress
            }
        }
    }
    return null
}