当前位置: 首页 > 知识库问答 >
问题:

vertx网络服务器只使用一个事件循环线程,而16个线程可用

羊舌阎宝
2023-03-14

我用Vert。xv3。5.1. 下面是最简单的代码示例:

vertx.createHttpServer()
                    .requestHandler(anyRouter::accept)
                    .listen(8080);

在我的例子中,事件循环组的大小是16,所以我预计我的请求将影响16个线程。服务器已成功启动,但只能在一个线程中运行。(我使用不同的tcp连接发送了请求,所以保持活动状态不是原因。)
HttpServerImpl包含httphandlermg,此管理器处理一组事件循环(名为availableWorkers)。在调试期间,我看到这个池只包含一个工人。

使用VerentleModel并不能解决这个问题,仍然不能使用所有的线程。

如果我在循环中多次创建服务器,它会有所帮助。因此,我有许多受影响的线程和一个共享服务器。但这看起来像是解决办法。

问题是如何创建使用所有可用事件循环线程的web服务器?

用下面的竖线实现

因此,这个实现使用了一半的可用线程(8个线程)。但我希望它使用16:)

public static void main(String[] args) throws Exception {
        int eventLoopSize = 16;
        Vertx vertx = new VertxOptions().setEventLoopPoolSize(eventLoopSize);
       for (int i=0;i<eventLoopSize; i++) {
           vertx.deployVerticle(new MyServer(vertx), deploymentOptions);
       }
    }

public class MyServer implements Verticle {
final Vertx vertx;
public MyServer(Vertx vertx) {
   this.vertx = vertx;
}

@Override
void init(Vertx vertx, Context context) {
vertx.createHttpServer()
                    .requestHandler(anyRouter::accept)
                    .listen(8080);
}
}

共有3个答案

公羊浩气
2023-03-14

经过一些尝试和讨论(感谢tsegismont),我了解到,使用池中所有线程的唯一正确方法是:

DeploymentOptions deploymentOptions = new DeploymentOptions()
        .setInstances(vertxOptions.getEventLoopPoolSize());

vertx.deployVerticle(() -> new MyServerVerticle(), deploymentOptions);

以下实现具有意外行为:

for (int i=0;i<vertxOptions.getEventLoopPoolSize();++i) {
   vertx.deployVerticle(new MyServerVerticle());
}

class MyServerVerticle implements Verticle {
 @Override
public void init(Vertx vertx, Context context) {
    this.vertx=vertx;
}

 @Override
 public void start(Future<Void> startFuture) throws Exception {
vertx.createHttpServer()
            .requestHandler(anyRouter::accept)
            .listen(8080);
}
}

并且没有正确的方法来创建不使用具有多个事件循环的垂直模型的网络服务器。在这种情况下,我们只能在循环中创建服务器,但我不确定它是否总是正确的:

class MyServerNotVerticle {
  public void start() {
   for (int i=0;i<vertxOptions.getEventLoopPoolSize();++i) {
       vertx.createHttpServer()
                .requestHandler(anyRouter::accept)
                .listen(8080);
    }
  }
}
何涵畅
2023-03-14

据此:https://vertx.io/docs/vertx-core/java/#_reactor_and_multi_reactor

即使一个Vertx实例维护多个事件循环,任何特定的处理程序都不会同时执行,而且在大多数情况下(工作垂直轴除外),总是使用完全相同的事件循环来调用。

因此,如果你想使用其他线程,你可以:

>

  • 在单独的PID中使用verticle的多个实例(例如,使用systemd services的多值实例,或docker容器,或任何允许您运行微服务的多个java进程并使监控和故障恢复更容易的东西)。

    多次将您的verticle部署为worker verticle:https://vertx.io/docs/vertx-core/java/#worker_verticles

    使用executeBlocking方法:https://vertx.io/docs/vertx-core/java/#blocking_code但我不建议你用这个。

    如果你的顶点暴露了一个超文本传输协议restful API,我建议你使用一个经典的超文本传输协议反向代理,并管理容器内的多个实例,或者如果你不能或端口使用不同的主机。并通过事件总线(或其他基于消息队列的系统)将操作委托给其他顶点。这里有一个设计的例子。

  • 太叔英卫
    2023-03-14

    只涉及一个线程,这正是事件循环模型。我建议看菲利普·罗伯茨:到底什么是事件循环?|JSConf EU 2014。示例适用于浏览器,但概念与Vert等服务器端事件循环系统相同。x或节点。

    然而,对于Vert。x您通常将代码组织在垂直链接中(比如小型服务)。每个垂直体都分配了一个事件循环,但您可以部署多个实例。这就是如何使用CPU的所有核心。如果你是一名Java程序员,正在编写Vert。我建议您第一次阅读本指南。

    至于将verticle扩展到所有核心,问题在于,当您自己实例化verticle时,实际上会创建单独的部署,并且无法保证使用不同的事件循环。

    如指定垂直实例数中所述,必须使用垂直名称:

    使用顶点名称部署顶点时,可以指定要部署的顶点实例数:

    DeploymentOptions options = new DeploymentOptions().setInstances(16);
    vertx.deployVerticle("com.mycompany.MyOrderProcessorVerticle", options);
    

    这对于跨多个核轻松扩展非常有用。例如,您可能需要部署一个web服务器垂直平台,并在您的机器上部署多个核心,因此您希望部署多个实例来利用所有核心。

     类似资料:
    • 我来自一个请求=一个线程的概念,现在我想使用来理解事件循环的概念。根据文档,如果我们使用阻塞操作,我们应该将其传递给方法。 我有一些问题与这一段从 这是我的代码: 我向 http 服务器发送 100 个请求,这是输出: 1) 事件循环如何在请求之间切换(从输出中,它首先得到一些请求,然后给出响应)? 2)我使用了< code>executeBlocking方法,但是您可以看到上面的代码只使用了名为

    • 顶点似乎只由单个线程执行,并且总是由同一个线程执行。但是Vert. x能够通过每个CPU创建一个线程来使用机器中的所有CPU。每个线程可以向多个顶点发送消息。 但在性能测试期间,在标准verticle上评测Vertex http服务器时,我只能看到一个线程处理所有处理(vert.x-eventloop-thread-0)。 我该怎么做才能让我的8个事件循环线程都处理到verticle的消息?

    • 我正在使用vert。x 2.1.5版本。我试图在我的项目中使用事件循环。下面给出了示例代码 在此代码中,我的事件总线在执行事件循环之前返回值。我需要根据事件循环输出填充我的输出 如何实现

    • 每个人希望您能在这方面帮助我:我有两个线程,负责处理来自客户端的连接。 这是我的密码 当我尝试两次连接到loginSocket时,服务器将阻塞并停止工作,从而阻塞客户端,但如果我删除以下内容,则不会发生这种情况: 我没有收到任何错误消息,那么为什么会发生这种情况,我如何修复?

    • 在Flink中,像“平面地图”、“地图”等运算符称为任务,如果我将平面地图的并行度设置为30,那么这个任务有30个子任务。 现在,如果我只有一个插槽,它会在一个插槽中产生多个线程吗?还是每个插槽只有一个线程? Flink会在该插槽中简单地创建30个线程,还是使用类似线程池的东西? 以上不是一个恰当的例子。 假设在作业中我有操作符flatMap和map,它们都有并行度1,我只有一个插槽,这个插槽会创

    • 我做了几个线程转储,发现有16个线程在等待同一个锁,例如: “__ejb-thread-pool1”守护进程prio=6 tid=0x39657c00 nid=0x1c08在条件[0x3297f000]java.lang.thread.state:waiting(parking)在sun.misc.unsafe.park(本机方法)-在java.util.concurrent.locks.lock