0

I need to set a request timeout on a downstream backend call. However, the WebClient class in Vert.x 3.9 doesn't seem to work as I expected. Here's some test code for it:

package client;

import io.vertx.reactivex.core.AbstractVerticle;
import io.vertx.reactivex.core.Vertx;
import io.vertx.reactivex.ext.web.client.WebClient;

public class Timeout extends AbstractVerticle {
  private static final int port = 8080;
  private static final String host = "localhost";
  private static final int timeoutMilliseconds = 50;

  @Override
  public void start() {
    WebClient client = WebClient.create(vertx);

    for (int i = 0; i < 100; i++) {
      client.get(port, host, "/").timeout(timeoutMilliseconds).send(
          ar -> {
            if (ar.succeeded()) {
              System.out.println("Success!");
            } else {
              System.out.println("Fail: " + ar.cause().getMessage());
            }
          }); 
    }

    vertx.timerStream(1000).handler(aLong -> { vertx.close(); });
  }

  public static void main(String[] args) {
    Vertx vertx = Vertx.vertx();
    vertx.deployVerticle(new Timeout());
  }
}

I'm running the following Go server on the same host for testing:

package main

import (
    "fmt"
    "net/http"
)

func main() {
    http.HandleFunc("/", HelloServer)
    http.ListenAndServe(":8080", nil)
}

func HelloServer(w http.ResponseWriter, r *http.Request) {
    fmt.Println("Saying hello!")
    fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:])
}

The output for my test server shows that WebClient opens 5 concurrent connections and every request is stopped by the timeout. What am I doing wrong here? How should I set a connection timeout on the requests? The output from the client is:

Fail: The timeout period of 50ms has been exceeded while executing GET / for server localhost:8080
Fail: The timeout period of 50ms has been exceeded while executing GET / for server localhost:8080
Fail: The timeout period of 50ms has been exceeded while executing GET / for server localhost:8080
Fail: The timeout period of 50ms has been exceeded while executing GET / for server localhost:8080
Fail: The timeout period of 50ms has been exceeded while executing GET / for server localhost:8080
Fail: The timeout period of 50ms has been exceeded while executing GET / for server localhost:8080
Fail: The timeout period of 50ms has been exceeded while executing GET / for server localhost:8080
...

I would expect to only see "Success!" printed, since the Go server running on the same host should respond well within 50ms.

EDIT: Removed the vertx.close() and clarified original question... Didn't actually have the vertx.close() in my original test code, but added it when editing the SO post, so people running it wouldn't need to hit CTRL-C.

eof
  • 413
  • 4
  • 14
  • what's the point of starting the vertx and killing it immediately after? You rather need a simple fire-off script in order to run some web-client requests... – injecteer Jul 07 '21 at 12:07

2 Answers2

1

It hangs because you are blocking the main thread.

Remove this:

    try {
      Thread.sleep(1000);
    } catch(InterruptedException ex) {
      Thread.currentThread().interrupt();
    }

    vertx.close();

The application will keep running as long as vert.x is alive.

If you really want to close vert.x yourself, do it in a separate thread.

Or alternatively, do it with Vert.x itself:

vertx.timerStream(1000).handler(aLong -> {
  vertx.close();
});
adnan_e
  • 1,764
  • 2
  • 16
  • 25
1

not sure what you are trying to do there, but there are multiple things that are incorrect there:

  1. in AbstractVerticle.start() you do only start logic. also if you have async logic, then you need to use an async interface like start(Promise<Void> startPromise) and report completion properly so that Vertx waits for your start logic to finish.

  2. you are blocking the start process here:

    try {
      Thread.sleep(1000);
    } catch(InterruptedException ex) {
      Thread.currentThread().interrupt();
    }

as long as this runs, your verticle is not really started and main thread of vertx is blocked.

  1. you never close vertx in a verticle's start! so remove this line vertx.close() and quit the running application in another way.

in general check docs to understand the process and usage of verticles.

mohamnag
  • 2,709
  • 5
  • 27
  • 40
  • Clarified the question. I'm seeing similar requests fired off e.g. here, so I don't think the timeouts are caused by blocking the thread: https://how-to.vertx.io/http-client-howto/ – eof Jul 07 '21 at 14:11
  • don't know what you see in the link, but on that page there is no request sent in start method. the sending operation is done in a periodic timer that runs off the main thread. – mohamnag Jul 07 '21 at 18:50
  • @eof Did you rule out the possibility that the request simply took longer than 50ms (for whatever reason)? Does the same behavior persist with values such as 500, or even 1000? – adnan_e Jul 07 '21 at 21:25