You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetty 9.4.10 HTTP客户端偶发EOFException错误求助

解决Jetty 9.4.10.v20180503 HTTP客户端偶发EOFException问题

我来帮你分析下这个偶发的EOFException问题,从你提供的异常堆栈(虽然末尾有截断,但核心信息足够)来看,问题根源是HttpReceiverOverHTTP.earlyEOF——也就是客户端在接收服务端响应的过程中,连接被提前关闭了,导致数据流意外终止。

先把异常堆栈整理出来方便查看:

java.io.EOFException: HttpConnectionOverHTTP@571103e6(l:/192.168.1.100:27497 <-> r:api.kucoin.com/13.113.121.24:443,closed=false)=&gt;HttpChannelOverHTTP@a423e61(exchange=HttpExchange@e7dbbf1 req=TERMINATED/null@null res=PENDING/null@null)[send=HttpSenderOverHTTP@4b7f345a(req=QUEUED,snd=COMPLETED,failure=null)[HttpGenerator@61d4e46c{s=START}],recv=HttpReceiverOverHTTP@7a7e7f01(rsp=IDLE,failure=null)[HttpParser{s=CLOSED,0 of -1}]]&lt;-DecryptedEndPoint@193ff18c{api.kucoin.com/13.113.121.24:443&lt;-&gt;/192.168.1.100:27497,OPEN,fill=-,flush=-,to=22604/0}-&gt;HttpConnectionOverHTTP@571103e6(l:/192.168.1.100:27497 &lt;-&gt; r:api.kucoin.com/13.113.121.24:443,closed=false)=&gt;HttpChannelOverHTTP@a423e61(exchange=HttpExchange@e7dbbf1 req=TERMINATED/null@null res=PENDING/null@null)[send=HttpSenderOverHTTP@4b7f345a(req=QUEUED,snd=COMPLETED,failure=null)[HttpGenerator@61d4e46c{s=START}],recv=HttpReceiverOverHTTP@7a7e7f01(rsp=IDLE,failure=null)[HttpParser{s=CLOSED,0 of -1}]]-&gt;SocketChannelEndPoint@2b50cb15{api.kucoin.com/13.113.121.24:443&lt;-&gt;/192.168.1.100:27497,ISHUT,fill=-,flush=-,to=21603/0}{io=0/0,kio=0,kro=1}-&gt;SslConnection@6de1ad97{NEED_WRAP,eio=-1/-1,di=-1}=&gt;HttpConnectionOverHTTP@571103e6(l:/192.168.1.100:27497 &lt;-&gt; r:api.kucoin.com/13.113.121.24:443,closed=false)=&gt;HttpChannelOverHTTP@a423e61(exchange=HttpExchange@e7dbbf1 req=TERMINATED/null@null res=PENDING/null@null)[send=HttpSenderOverHTTP@4b7f345a(req=QUEUED,snd=COMPLETED,failure=null)[HttpGenerator@61d4e46c{s=START}],recv=HttpReceiverOverHTTP@7a7e7f01(rsp=IDLE,failure=null)[HttpParser{s=CLOSED,0 of -1}]] at java.util.concurrent.CompletableFuture.encodeRelay(CompletableFuture.java:326) at java.util.concurrent.CompletableFuture.completeRelay(CompletableFuture.java:338) at java.util.concurrent.CompletableFuture.uniRelay(CompletableFuture.java:911) at java.util.concurrent.CompletableFuture$UniRelay.tryFire(CompletableFuture.java:899) at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:474) at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1977) at com.myapplication.ResponseListener.onComplete(ResponseListener.java:45) at org.eclipse.jetty.client.ResponseNotifier.notifyComplete(ResponseNotifier.java:193) at org.eclipse.jetty.client.ResponseNotifier.notifyComplete(ResponseNotifier.java:185) at org.eclipse.jetty.client.HttpReceiver.terminateResponse(HttpReceiver.java:464) at org.eclipse.jetty.client.HttpReceiver.abort(HttpReceiver.java:545) at org.eclipse.jetty.client.HttpReceiver.responseFailure(HttpReceiver.java:436) at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.failAndClose(HttpReceiverOverHTTP.java:369) at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.earlyEOF(HttpReceiverOverHTTP.java:338) at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:1476) at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.shutdown(HttpReceiverOverHTTP.java:209) at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.process(HttpReceiverOverHTTP.java:147) at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.receive(HttpReceiverOverHTTP.java:73) at org.eclipse.jetty.client.http.HttpChannelOverHTTP.receive(HttpChannelOverHTTP.java:133) at org.eclipse.jetty.client.http.HttpConnectionOverHTTP.onFillable(HttpConnectionOverHTTP.java:155) at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:281) at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:102) at org.eclipse.jetty.io.ssl.SslConnection.onFillable(SslConnection.java:291) at org.eclipse.jetty.io.ssl.SslConnection$3.succeeded(SslConnection.java:151) at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:102) at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118) at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:333) at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:310) at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:168) at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:126) at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:366) at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:760) at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:678) ... 1 common frames omitted Caused by: java.io.EOFException: HttpConnectionOverHTTP@571103e6(l:/192.168.1.100:27497 &lt;-&gt; r:api.kucoin.com/13.113.121.24:443,closed=false)=&gt;HttpChannelOverHTTP@a423e61(exchange=HttpExchange@e7dbbf1 req=TERMINATED/null@null res=PENDING/null@null)[send=HttpSenderOverHTTP@4b7f345a(req=QUEUED,snd=COMPLETED,failure=null)[HttpGenerator@61d4e46c{s=START}],recv=HttpReceiverOverHTTP@7a7e7f01(rsp=IDLE,failure=null)[HttpParser{s=CL

问题根源分析

这种偶发的EOFException通常由以下几种情况导致:

  • 服务端(api.kucoin.com)因负载过高、内部错误或超时策略,在未完整返回响应时就主动关闭了连接
  • 网络波动、防火墙拦截等外部因素导致连接中途断开
  • Jetty客户端的连接复用机制出现问题,复用了已经失效的长连接
  • Jetty版本较老,存在连接处理相关的已知bug

具体解决方案

1. 配置合理的超时参数

Jetty默认的超时设置可能不足以应对网络不稳定的场景,你可以明确设置连接超时、空闲超时和请求读取超时:

// 初始化HttpClient时设置全局超时
HttpClient httpClient = new HttpClient();
httpClient.setConnectTimeout(5000); // 连接超时5秒
httpClient.setIdleTimeout(10000); // 连接空闲超过10秒就关闭
httpClient.start();

// 针对单个请求设置读取超时
Request request = httpClient.newRequest("https://api.kucoin.com/your-api-path")
        .timeout(15000, TimeUnit.MILLISECONDS); // 15秒内未收到完整响应则超时

2. 启用连接池健康检查

Jetty的连接池可能会复用已经失效的连接,开启健康检查可以在复用前验证连接状态:

HttpClient httpClient = new HttpClient();
httpClient.getPool().setHealthCheck((connection, callback) -> {
    // 发送HEAD请求验证连接可用性
    connection.send(new Request.Head("/"), result -> {
        callback.succeeded(result.isSucceeded());
    });
});

3. 添加异常重试逻辑

因为异常是偶发的,你可以在代码中捕获EOFException并进行有限次数的重试(注意避免无限重试):

public CompletableFuture<ContentResponse> sendWithRetry(Request request, int maxRetries) {
    return request.send()
            .exceptionally(ex -> {
                if (ex.getCause() instanceof EOFException && maxRetries > 0) {
                    // 重试时需要重新创建请求对象,避免状态污染
                    Request newRequest = httpClient.newRequest(request.getURI())
                            .method(request.getMethod())
                            .headers(request.getHeaders());
                    return sendWithRetry(newRequest, maxRetries - 1).join();
                }
                throw new CompletionException(ex);
            });
}

4. 升级Jetty版本

你使用的Jetty 9.4.10是2018年的老版本,后续的9.4.x版本修复了大量连接处理的bug,建议升级到9.4.x的最新稳定版(比如9.4.52.v20230823),这能从根本上减少这类偶发问题。

5. 排查服务端侧问题

如果条件允许,可以联系kucoin的技术支持,或者查看他们的开发者文档,确认是否有特定的请求限制、超时设置,或者是否存在服务端侧的不稳定情况。

内容的提问来源于stack exchange,提问作者Gili

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:27:53