Vertx Http Webclient запрос зависает, даже если рабочие потоки доступны - PullRequest
0 голосов
/ 22 марта 2020

У меня есть программа, в которой я развернул рабочую версию (vertx версия 3.6.3). Исходя из этой рабочей статьи, я делаю HTTP-запрос с использованием библиотеки Vertx WebClient. Мой рабочий пул vertx равен 20, а событие l oop размером пула равно 10. Сразу после выполнения http-запроса (после вызова send ()) я блокирую рабочий поток, который выполнил HTTP-запрос (рабочий поток), используя завершаемый будущее. Когда я блокирую рабочий поток, HTTP-запрос никогда не отвечает и всегда истекает. Он отвечает, когда рабочий поток не заблокирован. Я подумал: если я блокирую рабочий поток, то в пуле будут другие рабочие потоки для выполнения HTTP-запросов. Что я здесь не так делаю? Кроме того, я включил активность сетевого журнала, но не вижу распечаток сетевых журналов в журналах.

Ниже приведена программа, которую я пробовал, и я запускаю пример HTTP-сервера, работающего на локальном хосте на порту 8080, который отвечает нормально.

import java.util.concurrent.TimeUnit;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.DeploymentOptions;
import io.vertx.core.Vertx;
import io.vertx.core.VertxOptions;
import io.vertx.core.buffer.Buffer;
import io.vertx.ext.web.client.HttpResponse;
import io.vertx.ext.web.client.WebClient;
import io.vertx.ext.web.client.WebClientOptions;

public class VertxTestMain extends AbstractVerticle {

    private static int workerPoolSize = 20;
    private static int eventLoopPoolSize = 10;

    @Override
    public void start() {
        vertx.eventBus().consumer("vertx.address", event -> {
            CompletableFuture<String> future = new CompletableFuture<>();
            doAHttpRequest(vertx, future);
            try {
                //future.get(20, TimeUnit.SECONDS);
            } catch (Exception e) {
                System.out.println(Thread.currentThread().getName()+ " ----- HTTP request never responded");
                e.printStackTrace();
            }
        });
    }

    private void doAHttpRequest(Vertx vertx, CompletableFuture<String> future)  {

        //System.setProperty("java.util.logging.config.file", "/opt/maglev/persisted/data/vertx-default-jul-logging.properties");

        WebClientOptions options = new WebClientOptions();
        options.setLogActivity(true);
        WebClient webClient = WebClient.create(vertx, options );

        int port = 8080;
        String host = "localhost";
        String url = "/";

        System.out.println(Thread.currentThread().getName()+ " ----- Sending http://" + host + ":" + port + "/" + url);

        // Send a GET request
        webClient
        .get(port, host, url)
        .timeout(10000)
        .send(ar -> {
            if (ar.succeeded()) {
                HttpResponse<Buffer> response = ar.result();
                System.out.println(Thread.currentThread().getName()+ " ----- Received response.  " + response.bodyAsString());
                System.out.println(Thread.currentThread().getName()+ " ----- Received response with status code.  " + response.statusCode());
                future.complete("success");
            } else {
                System.out.println(Thread.currentThread().getName()+ " ----- Something went wrong. " + ar.cause().getMessage());
                future.completeExceptionally(ar.cause());
            }
        });
    }

    public static void main(String[] args) {

        DeploymentOptions deploymentOptions = new DeploymentOptions().setWorker(true).setInstances(2);
        VertxOptions vertxOptions = new VertxOptions();
        vertxOptions.setWorkerPoolSize(workerPoolSize);
        vertxOptions.setEventLoopPoolSize(eventLoopPoolSize);
        Vertx vertx = Vertx.vertx(vertxOptions);

        vertx.deployVerticle(VertxTestMain.class.getName(), deploymentOptions, event -> {
            if(event.succeeded()) {
                System.out.println(Thread.currentThread().getName()+ " ----- VertxTestMain verticle is deployed");
                vertx.eventBus().send("vertx.address", "send");
            }
            else {
                System.out.println(Thread.currentThread().getName()+ " ----- VertxTestMain verticle deployment failed. " + event.cause());
            }
        });
    }
}

1 Ответ

0 голосов
/ 22 марта 2020

Вы не разрешаете запуск своего HTTP-запроса.

Возвращайте Future из вашего метода вместо его передачи:

private CompletableFuture<String> doAHttpRequest(Vertx vertx)  {

    CompletableFuture<String> future = new CompletableFuture<>();
    WebClientOptions options = new WebClientOptions();
    options.setLogActivity(true);
    WebClient webClient = WebClient.create(vertx, options );

    int port = 8080;
    String host = "localhost";
    String url = "/";

    System.out.println(Thread.currentThread().getName()+ " ----- Sending http://" + host + ":" + port + "/" + url);

    // Send a GET request
    webClient
    .get(port, host, url)
    .timeout(10000)
    .send(ar -> {
        if (ar.succeeded()) {
            HttpResponse<Buffer> response = ar.result();
            System.out.println(Thread.currentThread().getName()+ " ----- Received response.  " + response.bodyAsString());
            System.out.println(Thread.currentThread().getName()+ " ----- Received response with status code.  " + response.statusCode());
            future.complete("success");
        } else {
            System.out.println(Thread.currentThread().getName()+ " ----- Something went wrong. " + ar.cause().getMessage());
            future.completeExceptionally(ar.cause());
        }
    });

    return future;
}

Вы также можете повторно использовать WebClient, есть нет необходимости создавать его для каждого запроса.

Кроме того, обратите внимание на Promise API Vert.x, поскольку он может лучше подходить для вашего варианта использования:

https://vertx.io/docs/apidocs/io/vertx/core/Promise.html

...