0

我需要在下游后端调用上设置请求超时。但是,Vert.x 3.9 中的 WebClient 类似乎并没有像我预期的那样工作。这是它的一些测试代码:

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());
  }
}

我在同一台主机上运行以下 Go 服务器进行测试:

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:])
}

我的测试服务器的输出显示 WebClient 打开了 5 个并发连接,并且每个请求都因超时而停止。我在这里做错了什么?我应该如何为请求设置连接超时?客户端的输出是:

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
...

我希望只看到“成功!” 打印出来,因为运行在同一主机上的 Go 服务器应该在 50 毫秒内响应良好。

编辑:删除了 vertx.close() 并澄清了原始问题...在我的原始测试代码中实际上没有 vertx.close() ,但是在编辑 SO 帖子时添加了它,所以运行它的人不需要按CTRL-C。

4

2 回答 2

1

它挂起是因为您阻塞了主线程。

删除这个:

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

    vertx.close();

只要 vert.x 存在,应用程序就会一直运行。

如果您真的想自己关闭 vert.x,请在单独的线程中进行。

或者,使用 Vert.x 本身执行此操作:

vertx.timerStream(1000).handler(aLong -> {
  vertx.close();
});
于 2021-07-07T11:57:11.740 回答
1

不确定您要在那里做什么,但是那里有很多不正确的事情:

  1. AbstractVerticle.start()你做的只是开始逻辑。此外,如果您有异步逻辑,那么您需要使用类似的异步接口start(Promise<Void> startPromise)并正确报告完成,以便 Vertx 等待您的启动逻辑完成。

  2. 您在这里阻止了启动过程:

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

只要它运行,您的verticle就没有真正启动并且vertx的主线程被阻塞。

  1. 你永远不会在verticle的开始时关闭vertx!所以删除这一行vertx.close()并以另一种方式退出正在运行的应用程序。

通常检查文档以了解 Verticle 的过程和用法。

于 2021-07-07T12:07:48.543 回答