我设置了一个小项目,用于在集群环境中学习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个主要类和大量脚本
答案 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
}