【问题标题】:Vertx's netty event loop using only single threadVertx 的 netty 事件循环仅使用单线程
【发布时间】:2020-08-31 21:02:38
【问题描述】:

似乎一个verticle只能由一个线程执行,并且总是由同一个线程执行。 但是 Vert.x 能够通过为每个 CPU 创建一个线程来使用机器中的所有 CPU。 每个线程可以向多个 Verticle 发送消息。

但是在性能测试期间在标准 Verticle 上分析 vertx http 服务器时,我只能看到 1 个线程处理所有处理 (vert.x-eventloop-thread-0)。

我可以做些什么来让我的所有 8 个事件循环线程处理到 Verticle 的消息?

CountDownLatch latch = new CountDownLatch(1);
final List<Throwable> errors = new ArrayList<>();

local = new Local(getVertx(), settings, options, connectionHandler, exceptionHandler);

LocalVerticle.vertxDeployMap.put(local.hashCode(), local);

DeploymentOptions dop = new DeploymentOptions()
        .setInstances(new VertxOptions()
        .getEventLoopPoolSize())
        .setConfig(new JsonObject().put("local", local.hashCode()));

Network.getVertx().deployVerticle(LocalVerticle.class.getName(), dop, (event) -> {
    if (!event.failed()) {
        latch.countDown();
    } else {
        errors.add(event.cause());
    }
});

boolean await = latch.await(10, TimeUnit.SECONDS);
if (!await) {
    if (errors.isEmpty()) {
        throw new Exception("Failed to initialize Local Verticle");
    } else {
        throw new Exception("Failed to initialize Local Verticle", errors.get(0));
    }
}

LocalVerticle.vertxDeployMap.remove(local.hashCode());


public class LocalVerticle extends AbstractVerticle {

    static final Map<Integer, Local> vertxDeployMap = new HashMap<>();
    
    private HttpServer httpServer;

    @Override
    public void start() throws Exception {
        
        Local local = vertxDeployMap.get(this.config().getInteger("local"));

        HttpServerOptions options = local.getOptions();
        Handler<HttpConnection> connectionHandler = local.getConnectionHandler();
        Handler<Throwable> exceptionHandler = local.getExceptionHandler();
        Router router = local.getRouter();

        this.httpServer = this.vertx
                .createHttpServer(options)
                .exceptionHandler(exceptionHandler)
                .connectionHandler(connectionHandler)
                .requestHandler(router)
                .listen();

    }

    @Override
    public void stop() throws Exception {
        if (this.httpServer != null) {
            this.httpServer.close();
            this.httpServer = null;
        }
    }
}

【问题讨论】:

    标签: netty vert.x event-loop


    【解决方案1】:

    Vert.x 线程模型的设计使得部署的 Verticle 的特定实例始终锁定到单个线程。为了跨内核扩展您的应用程序,您需要deploy multiple instances of your Verticle

    使用 Verticle 名称部署 Verticle 时,您可以指定要部署的 Verticle 实例的数量:

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

    这对于跨多个内核轻松扩展很有用。例如,您可能需要部署一个 Web 服务器 Verticle,并在您的机器上部署多个核心,因此您希望部署多个实例以利用所有核心。

    【讨论】:

    • 感谢您的指点。这有帮助。但是在这个 vertx 上创建的 http 服务器并没有平等地使用所有部署的 Verticle。有没有办法向 http 服务器指示在所有这些 Verticle 上进行扩展?
    • “不均等地使用所有部署的verticles”是什么意思?如果你想要一个 http 服务器跨核心扩展,你必须部署多个创建 http 服务器的 verticle 实例,并让所有实例将服务器绑定到同一个端口。 Vert.x 足够智能,可以跨 HTTP 服务器的所有实例循环请求。
    • 我在上面添加了我的基本代码结构。并且正在将请求发送到服务器并在 http 服务器上的路由器上的处理程序中添加小的处理延迟,以影响事件循环线程的扩展。分析器仍然显示只有 1 个线程处理过处理。也许我们需要使用 Verticle 类本身的 start 或 init 方法?
    • 我对你的代码有点困惑。您正在部署 8 个 Verticle 实例,但它似乎实际上并没有做任何事情。那里有你不分享的代码吗?如果您只是在任何 Verticle 之外创建 HttpServer 的单个实例,则所有端点的处理程序都将在单个线程中执行。为了使 HttpServer 的处理程序跨内核扩展,您必须在 Verticle inside 中创建 HttpServer(在其 start 方法中),并部署该 Verticle 的多个实例。
    • 好的,我明白你的意思了。我将其设置为这样做,但努力将所需的参数(通过上下文)传递给 Verticle 的启动函数(http 服务器选项、路由器、处理程序)。看到 AbstractVerticle 上的成员 Context 和我用“getOrCreateContext” API 创建的不一样。
    猜你喜欢
    • 1970-01-01
    • 2018-09-21
    • 1970-01-01
    • 2021-07-25
    • 1970-01-01
    • 2017-09-17
    • 2022-06-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多