java - Vertx 运行多个事件循环

我遇到了需要纵向扩展的情况,所以我最终得到了一个具有 20 核5GB 的虚拟机。

问题是,当我加载大量数据时,我看不到 CPU 只使用了一个内核。我希望看到 20 个内核并行 运行。

我尝试使用 100 线程的 Worker 创建我的 Vertx

VertxOptions options = new VertxOptions().setWorkerPoolSize(100);
this.asyncFlowVertx = Vertx.vertx(options);

但我的服务仍然没有使用所有内核。

我还可以配置什么以允许我的服务器并行运行更多请求?

有了这段代码,我如何在没有绑定(bind)地址异常的情况下部署多个 Verticle

@Override
public void start(Promise<Void> startPromise) {
    logger.info("Preparing Async Flow Http proxy server....");
    Router router = Router.router(asyncFlowVertx);
    router.route().handler(BodyHandler.create());
    router.route(GET, "/ready").respond(ctx -> Future.succeededFuture());
    router.route(GET, "/health").respond(ctx -> Future.succeededFuture());
    router.route(POST, "/request").respond(this::processRequest);
    router.route(POST, "/response").respond(this::processResponse);

    server = asyncFlowVertx.createHttpServer();
    server.requestHandler(router).listen(port, http -> {
        if (http.succeeded()) {
            logger.info("Async-flow-http-proxy running......");
            startPromise.complete();
        } else {
            startPromise.fail(http.cause());
        }
    });
}

如果我尝试

DeploymentOptions options = new DeploymentOptions().setInstances(20);
vertx.deployVerticle("com.bla.MyVerticle", options);

我得到绑定(bind)地址异常

解决方案

我设法部署了多个 Verticle,但即使部署了 20 个,我也只能在我的日志中看到运行两个事件循环线程

var vertx = Vertx.vertx();
Router router = Router.router(vertx);
IntStream.range(0,20).forEach(i -> {
    logger.info("Creating Vertx Verticle {}", i);
    vertx.deployVerticle(new AsyncFlowHttpProxy(router));
});

我的 Verticle 在构造函数中需要一些依赖项,如果我尝试像这样创建多个 Verticle

VertxOptions options = new VertxOptions();
    options.setWorkerPoolSize(100);
    var vertx = Vertx.vertx(options);
    Router router = Router.router(vertx);
    DeploymentOptions deploymentOptions = new DeploymentOptions().setInstances(20);
    vertx.deployVerticle(new AsyncFlowHttpProxy(port, nextServicePort, nextServiceName, router), deploymentOptions);

我遇到了这个错误

java.lang.IllegalArgumentException: Can't specify > 1 instances for already created verticle

知道为什么吗?

问候

最佳答案

Verticle 的实例默认有一个事件循环池,线程数 = 2 * 机器上的核心数。为了便于讨论,让我们假设有 x 个具有超线程的物理内核;这意味着有 2x 个虚拟内核。

这并不意味着 Verticle 的单个实例将立即创建最大数量的线程,这将相应地利用所有虚拟核心,而超线程会导致所有 x 物理核心被利用(这是由操作系统管理的)。这将更接近于多线程行为,而不是像 Vert.x 这样的框架的响应式(Reactive)、事件驱动的行为。

在Vert.x中,实际创建的线程数是由框架动态管理的。 Here是对相同的很好的分析。坚持 Vert.x 的设计原则,例如编写非阻塞代码,利用工作池将是优化性能的方法。专门针对实例数量,我找到了 this这建议从每个物理核心一个实例开始,然后扩展到测试。

这是我用来测试您的示例的完整代码,我可以在其中部署具有多个实例的 Verticle。

public class TestVerticle extends AbstractVerticle {

    private static final Logger LOGGER = LoggerFactory.getLogger(TestVerticle.class);

    private static Vertx vertx;

    public static void main(String[] args) {
        VertxOptions options = new VertxOptions().setWorkerPoolSize(100);
        DeploymentOptions deploymentOptions = new DeploymentOptions().setInstances(20);
        vertx = Vertx.vertx(options);
        vertx.deployVerticle(TestVerticle.class, deploymentOptions);
    }

    @Override
    public void start(Promise<Void> startPromise) {
        LOGGER.info("Preparing Async Flow Http proxy server....");
        Router router = Router.router(vertx);
        router.route().handler(BodyHandler.create());
        router.route(GET, "/ready").respond(ctx -> Future.succeededFuture());
        router.route(GET, "/health").respond(ctx -> Future.succeededFuture());
        router.route(GET, "/request").respond(ctx -> Future.succeededFuture(new JsonObject().put("hello", "world")));

        HttpServer server = vertx.createHttpServer();
        server.requestHandler(router).listen(8080, http -> {
            if (http.succeeded()) {
                LOGGER.info("Async-flow-http-proxy running......");
                startPromise.complete();
            } else {
                startPromise.fail(http.cause());
            }
        });
    }
}

https://stackoverflow.com/questions/72454356/

相关文章:

javascript - javascript(ASP.Net)中的计时器倒计时

python - SQLAlchemy 不插入默认值

javascript - 我如何构建一个用一组新按钮回复的不和谐按钮

javascript - 使用 react-chartjs-2 创建对折线图的引用

java - 如何使用二维指针通过 JNA 调用 C 函数?

flutter - 如何更新 flutterfire_web_sdk_version 以及如何启用

c# - 如何转义和忽略 __debugbreak

python - 直接查询 Sqlalchemy-utils EncrytedType 作为 SQL

python - 如何授予应用程序(而非用户本身)对文件夹和文件的权限

javascript - 未捕获的类型错误 : Failed to resolve module s