我正在使用 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 版本上运行,并且我读过的所有错误都早在那之前就已修复。
关于可能导致此问题的原因,或如何重现或进一步调试它的任何建议?