Java Vertx实例化多个垂直实例,侦听同一套接字
我正在开发一个数据报服务器,它监听特定端口上的消息,我们正在使用VertxJava框架来实现同样的功能。如果在启动垂直部署时在部署选项中只指定一个实例,那么一切都可以正常工作。一旦我指定了多个实例,就会出现套接字绑定错误。我理解,在一台机器上,一旦一个套接字被打开,如果我们尝试在同一个套接字上再次侦听,就会导致这个错误。但是为了利用多核处理器,我需要在同一个垂直处理器的多个实例之间共享数据报套接字。我不知道如何使用vertx框架实现这一点。下面我提到了我正在尝试实现相同功能的代码片段。请告诉我哪里出了问题Java Vertx实例化多个垂直实例,侦听同一套接字,java,sockets,udp,rx-java,vert.x,Java,Sockets,Udp,Rx Java,Vert.x,我正在开发一个数据报服务器,它监听特定端口上的消息,我们正在使用VertxJava框架来实现同样的功能。如果在启动垂直部署时在部署选项中只指定一个实例,那么一切都可以正常工作。一旦我指定了多个实例,就会出现套接字绑定错误。我理解,在一台机器上,一旦一个套接字被打开,如果我们尝试在同一个套接字上再次侦听,就会导致这个错误。但是为了利用多核处理器,我需要在同一个垂直处理器的多个实例之间共享数据报套接字。我不知道如何使用vertx框架实现这一点。下面我提到了我正在尝试实现相同功能的代码片段。请告诉我哪
public class TestServer extends AbstractVerticle {
@Override
public void start(Future<Void> startFuture) throws Exception {
DatagramSocket accessSocket = vertx.createDatagramSocket(new DatagramSocketOptions());
int accessPort=1234;
accessSocket.listen(accessPort, "0.0.0.0", asyncResult -> {
if (asyncResult.succeeded()) {
accessSocket.handler(packet -> {
logger.error("Received on Port "+packet);
InetSocketAddress localAddress = new InetSocketAddress(accessSocket.localAddress().host(), accessSocket.localAddress().port());
InetSocketAddress remoteAddress = new InetSocketAddress(packet.sender().host(), packet.sender().port());
Buffer data = packet.data();
try {
//handlePacket(localAddress, remoteAddress, decodePacket);
} catch (Exception e) {
System.out.println("listen Error while processing the packet " +packet, e);
}
});
} else {
System.out.println(" listen startAccessServer Failed " + asyncResult.cause());
}
});
}
/*
@Override
public void start(Future<Void> fut) {
vertx
.createHttpServer()
.requestHandler(r -> {
r.response().end("<h1>Hello from Vertx " +
"</h1>");
})
.listen(8080, result -> {
if (result.succeeded()) {
fut.complete();
} else {
fut.fail(result.cause());
}
});
}
*/
public static void main(String[] args) {
DeploymentOptions options = new DeploymentOptions();
//options.setInstances(1);
options.setInstances(Runtime.getRuntime().availableProcessors());
Vertx.vertx().deployVerticleObservable(TestServer.class.getName(),options).subscribe();
System.out.println("Server Started ");
}
}
公共类TestServer扩展了AbstractVerticle{
@凌驾
public void start(Future startFuture)引发异常{
DatagramSocket accessSocket=vertx.createDatagramSocket(新DatagramSocketOptions());
int accessPort=1234;
侦听(accessPort,“0.0.0.0”,asyncResult->{
if(asyncResult.successed()){
accessSocket.handler(数据包->{
记录器错误(“在端口上接收”+数据包);
InetSocketAddress localAddress=新的InetSocketAddress(accessSocket.localAddress().host(),accessSocket.localAddress().port());
InetSocketAddress remoteAddress=新的InetSocketAddress(packet.sender().host(),packet.sender().port());
缓冲区数据=packet.data();
试一试{
//handlePacket(本地地址、远程地址、解码数据包);
}捕获(例外e){
System.out.println(“处理数据包时侦听错误”+数据包,e);
}
});
}否则{
System.out.println(“侦听startAccessServer失败”+asyncResult.cause());
}
});
}
/*
@凌驾
公共空间启动(未来未来未来){
顶点
.createHttpServer()
.requestHandler(r->{
r、 response().end(“来自Vertx的你好”+
"");
})
.听(8080,结果->{
if(result.successed()){
fut.complete();
}否则{
进一步失败(result.cause());
}
});
}
*/
公共静态void main(字符串[]args){
DeploymentOptions=新的DeploymentOptions();
//选项。设置实例(1);
options.setInstances(Runtime.getRuntime().availableProcessors());
Vertx.Vertx().deployVerticleObservable(TestServer.class.getName(),options.subscribe();
System.out.println(“服务器已启动”);
}
}
只要我运行这段代码,就会产生套接字绑定异常,第一个垂直实例除外。如果我指定options.setInstances(1),问题会得到解决,但只会启动一个垂直实例。我知道我可能可以使用eventbus解决这个问题,但我现在不想朝这个方向走,除非我没有其他选择
这里最有趣的部分是,如果我注释掉第一个启动方法,其中我实现了数据报套接字,并取消注释第二个启动方法,其中我使用相同的部署选项在端口8080上启动httpserver,那么我根本看不到发生此套接字绑定异常
我相信我的数据报套接字实现中缺少了一些东西,这导致了这个问题。请让我知道使用vertx框架解决此问题的正确方法 从3.3.3开始,数据报服务器不支持负载平衡。我创建这个来跟踪问题 作为一种解决方法,您可以将
reuseAddress
标志设置为rue。这将避免出现BindException
,但只有一个verticle实例将接收消息
综上所述,根据您的用例,单个事件循环可能足以处理您的负载。我建议在使用事件总线尝试解决方法之前对其进行负载测试。请检查-@PavanKumar我要询问运行UDP服务器的DatagramSocket的具体情况,你提到的答案是关于TCP服务器的,我承认它在我的问题中工作正常。你可以阅读更多关于它的内容@。答案的第二部分是关于它使用eventBus的地方-你检查过这个解决方案吗?我相信这会有所帮助。现在滚动到回答中的部分-
了解您应该如何做:
@PavanKumar,感谢您尝试帮助我,但请完整阅读我的问题。我已经详细说明了事件总线解决方案,在这篇文章中,我正在寻找类似于HttpServer实现的东西,在HttpServer实现中,vertx实例是共享的,而不是基于事件总线的解决方案。很抱歉遗漏了这一部分。刚刚对答案中的问题投了赞成票。您也可以这样做以获得更好的可视性。您是否发现使用基于事件总线的方法有任何性能问题或缺点?通过消息总线发送消息不是免费的。尤其是在集群模式下。因此,如果您可以使用单个垂直通道(通过负载测试进行验证),请保持简单。由于它将是一个基于SNMP协议的智能事件监视系统,数百万设备将发送更新,因此负载将非常沉重。所以我需要在这里说明可伸缩性。我们正在评估vertx,因为它是polygot,因此,我们可以让我们的社区用户在我们的平台上开发插件,以定制我们的产品。我认为,根据您的建议,我需要通过httpserver实现并自己实现类似的方法,使用datagram socket进行负载共享,或者完全开发此组件而不使用vertx。我只能建议投票支持GitHub问题,以便在将来的版本中包含它。