Vert.x 3.9 WebClient 中的超时未按预期工作

问题描述

我需要在下游后端调用上设置请求超时。但是,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。

解决方法

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

删除这个:

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

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

  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() 并以另一种方式退出正在运行的应用程序。

一般检查文档以了解顶点的过程和用法。