2

我正在使用 Java 11 的HttpClient. 客户端间歇性挂起,我不知道为什么——我不知道是什么导致了挂起,也不知道如何重现它。

构建客户端和请求的代码位于不同的位置,因此此摘要显示了它们是如何构建的:

// excerpt 1: constructing the client
private HttpClient httpClient = HttpClient.newBuilder()
      .connectTimeout(Duration.ofSeconds(5))
      .build();

// excerpt 2: constructing the request
HttpRequest req = HttpRequest.newBuilder()
        .GET()
        .uri(...)
        .header(...)
        .header(...)
        .timeout(Duration.ofSeconds(5))
        .build();

// excerpt 3: sending the request
HttpResponse<String> resp = httpClient.send(req, BodyHandlers.ofString());

最初,我所知道的只是我的服务被挂起——我不知道HttpClient参与其中。然后,我在后台线程中扔了一个看门狗计时器,该线程持有对主工作线程的(弱)引用,这样如果计时器到期,我可以获得主工作线程正在做什么的堆栈跟踪。这给了我这个堆栈跟踪(五分钟后过期):

j.u.c.TimeoutException: null // I crammed the thread's stack trace into an exception to play nice with Splunk
    at j.i.m.Unsafe.park(Unknown Source)
    at j.u.c.l.LockSupport.park(Unknown Source)
    at j.u.c.CompletableFuture$Signaller.block(Unknown Source)
    at j.u.c.ForkJoinPool.managedBlock(Unknown Source)
    at j.u.c.CompletableFuture.waitingGet(Unknown Source)
    at j.u.c.CompletableFuture.get(Unknown Source)
    at j.i.n.h.HttpClientImpl.send(Unknown Source)
    at j.i.n.h.HttpClientFacade.send(Unknown Source)
    at c.a.x.d.c.MyClientClass.sendRequest(MyClientClass.java:163)
    at ...

从那以后,我已经看到其中一些超时发生在所有使用的代码的不同部分中HttpClient,都产生相同的堆栈跟踪。

我知道HttpClient可以追溯到 Java 9 的错误可能会导致挂起,但我们正在上个月(IIRC)的 Java 11 版本上运行,并且我读过的所有错误都早在那之前就已修复。

关于可能导致此问题的原因,或如何重现或进一步调试它的任何建议?

4

0 回答 0