如何运行 Vert.x 中的多个顶点?

How to run multiple vertices in Vert.x?

我是 Vert.x 的新手,我想通过 jar 运行 多个 Verticle。我有两个文件,一个是 MyFirstVertice.java,它路由路径“/q1/”和 return。第二个是 MySecondVertice.java,它路由路径“/q2/”。第二个顶点部署在第一个顶点。

MyFirstVertice.java

public class MyFirstVerticle extends AbstractVerticle {
@Override
public void start(Future<Void> fut) throws Exception {

    HttpServer server = vertx.createHttpServer();
    Router router = Router.router(vertx);
    router.route("/q1/*").handler(routingContext -> {
        HttpServerRequest request = routingContext.request();
        String Y = request.getParam("key");
        String cipherText = request.getParam("message");

        HttpServerResponse response = routingContext.response();

        response.setChunked(true);
        response.putHeader("content-type", "text/plain");
        response.write(Y + "\n");
        response.write(cipherText + "\n");
        response.end();

        vertx.deployVerticle(new MySecondVerticle(), stringAsyncResult -> {
            System.out.println("Second verticle is deployed successfully.");
        });
    });

    server.requestHandler(router::accept).listen(8080, httpServerAsyncResult -> {
        if (httpServerAsyncResult.succeeded()) {
            fut.complete();
        } else {
            fut.fail(httpServerAsyncResult.cause());
        }
    });
}

}

MySecondVetice.java

public class MySecondVerticle extends AbstractVerticle {
@Override
public void start(Future<Void> fut) throws Exception {

    HttpServer server = vertx.createHttpServer();
    Router router = Router.router(vertx);
    router.route("/q2/*").handler(routingContext -> {
        HttpServerResponse response = routingContext.response();
        response.setChunked(true);
        response.putHeader("content-type", "text/plain");

        response.end("q2");
    });

    server.requestHandler(router::accept).listen(8080, httpServerAsyncResult -> {
        if (httpServerAsyncResult.succeeded()) {
            fut.complete();
        } else {
            fut.fail(httpServerAsyncResult.cause());
        }
    });
}

}

我的pom.xml

<plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>2.3</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <transformers>
                            <transformer
                                    implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <manifestEntries>
                                    <Main-Class>io.vertx.core.Starter</Main-Class>
                                    <Main-Verticle>tutorial.diluo.MyFirstVerticle</Main-Verticle>
                                </manifestEntries>
                            </transformer>
                        </transformers>
                        <artifactSet/>
                        <outputFile>${project.build.directory}/${project.artifactId}-${project.version}-fat.jar</outputFile>
                    </configuration>
                </execution>
            </executions>
        </plugin>

我运行它通过java -jar xxx-fat.jar

当我在浏览器中输入localhost:8080/q1/xxx时,它可以return想要的内容。但是当我尝试访问 localhost:8080/q2/xxx 时,它显示 "Resource Not Found"。你能告诉我如何部署路由不同路径的两个 Verticle 吗?我知道我可以在同一个 Verticle 中路由不同的路径,我只想知道如何部署和 运行 多个顶点。提前致谢!

您遇到的问题是 Verticles 都试图绑定到同一个端口 (8080),而您不能这样做。 所以第二个 Verticle 很可能抛出一个 BindException 而没有出现。那么第一个 Verticle/q2 没有资源,这就是为什么你得到 Resource Not Found.

根据 tsegismont 的评论更新:

Vert.x 允许多个 Verticle 在称为 server sharing 的特性中的同一个端口上启动。当发生这种情况时,Vert.x 将使用循环策略轮流向每个 Verticle 发送请求。因此,您应该看到 50% 的请求适用于 /q1,50% 的请求适用于 /q2。但是 - 正如 tsegismont 所指出的,您的浏览器使用 persistent connections,因此它保持与单个 Verticle 的连接。您应该会发现使用 curl 或其他浏览器可能会给您带来更好的结果。无论哪种方式,这可能都不是您想要的。

如果你需要2个Verticles,你应该考虑一下。通常,您希望将 Verticle 视为应用程序的入口点 - 这是 bootstrapping 您的应用程序/微服务的一种方式。

如果您确实需要 2 个 Verticles,那么您将不得不选择单独的端口或在单独的框中选择 运行。如果不这样做,则只需在同一个 router 上创建 2 routes

有关 Vert.x Web

的更多信息,请参阅 http://vertx.io/docs/vertx-web/java/

不太清楚您想实现什么,但即便如此,您也不能 运行 两个 HTTP 服务器绑定到同一个端口 — 或几乎任何东西。

您需要为您的方法声明不同的端口,或者——这是我最喜欢的方法——只有一个 HTTP 服务器和其中的 "spawn multiple instances"。您可以阅读更多相关信息 here

对于您的情况,您可以安全地删除MySecondVetice.java;更新 MyFirstVertice.java 并包含 /q2/* 端点(及其处理程序)。然后,你需要在部署时做一些修改(你没有部署的代码 MyFirstVertice.java 所以我会 "improvise" 在这件事上:

@Slf4j
public final class Application extends AbstractVerticle {
  @Override
  public void start(final Future<Void> startFuture) {
    deploy(MyFirstVertice.class, new DeploymentOptions().setInstances(4));
    LOGGER.info("Module(s) and/or verticle(s) deployment...DONE");
    //startFuture.complete();
  }

  @Override
  public void stop(final Future<Void> stopFuture) {
    LOGGER.debug("Undeploying verticle(s)...DONE");
    LOGGER.info("Application stopped successfully. Enjoy the elevator music while we're offline...");
    stopFuture.complete();
  }

  private void deploy(final Class<? extends AbstractVerticle> clazz, final DeploymentOptions options) {
    vertx.deployVerticle(clazz.getName(), options, handler -> {
      if (handler.succeeded()) {
        LOGGER.debug("{} started successfully (deployment identifier: {})", clazz.getSimpleName(), handler.result());
      } else {
        LOGGER.error("{} deployment failed due to: ", clazz.getSimpleName(), handler.cause());
        //stop();
      }
    });
  }
}

为了澄清,请注意 Vertx 文档在某些情况下可能会产生误导,并且在许多帖子和许多网站中一直是一个混淆点。该文档指出多个垂直行业可能 运行 在同一个端口上。这显然并不意味着具有两个不同目的的两个垂直方向可以监听同一个端口。 IE。如果第一个垂直方向正在监听“\hello”而第二个垂直方向正在监听“\world”,那么这是一个不正确的设置。不知何故,当意思是“同一垂直的多个 objects/instantiations 可以 运行 在同一端口上时,这在“多个垂直侦听同一端口是可能的”的翻译中丢失了。”