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

使用Apache CloseableHttpAsyncClient识别不可访问URL避免404触发超时重试

解决方案

根因说明

你遇到的问题本质是部分异常服务端返回404状态码后,既不主动关闭连接,也不发送完整的响应内容,导致客户端一直挂起等待读取,直到触发10秒SocketTimeout,而你当前的重试逻辑又会对超时异常触发重试,最终导致无效请求额外产生20秒延迟。

具体优化方案

1. 新增响应状态码前置校验逻辑

拿到HttpResponse实例后第一时间校验状态码,4xx/5xx类错误直接抛出对应业务异常,不要继续读取响应内容,避免无意义等待:

Future<HttpResponse> httpResponseFuture = asyncCloseableHttpClient.execute(httpUriRequest, null);
try {
    HttpResponse response = httpResponseFuture.get(10000, TimeUnit.MILLISECONDS);
    // 新增状态码校验
    int status = response.getStatusLine().getStatusCode();
    if (status == HttpStatus.SC_NOT_FOUND) {
        throw new DownloadResourceNotFoundException("Resource not found, status code: 404");
    }
    if (status >= 400) {
        throw new DownloadFailedException("Request failed with status code: " + status);
    }
    return response;
} catch (ExecutionException e) {
    // 原有异常处理逻辑保持不变
    Throwable cause = e.getCause() != null ? e.getCause() : e;
    if (cause instanceof ConnectException) {
        throw new DownloadConnectionException("ConnectionException " + cause, DOWNLOAD_FAILED, cause);
    }
    if (cause instanceof SocketTimeoutException) {
        throw new DownloadTimeoutException(DOWNLOAD_TIMEOUT_EXCEPTION);
    }
    if (cause instanceof ConnectionClosedException) {
        throw new DownloadConnectionClosedException("ConnectionClosedException " + DOWNLOAD_FAILED, cause);
    }
    if(cause instanceof UnsupportedCharsetException) {
        throw new BadRequestException("Image download failed with UnsupportedCharsetException " + cause,
            INVALID_CONTENT_TYPE_EXCEPTION, cause);
    }
} catch (TimeoutException e) {
    throw new DownloadTimeoutException(DOWNLOAD_TIMEOUT_EXCEPTION);
}

注意:需要先自定义DownloadResourceNotFoundException等业务异常,不要归类到超时异常类。

2. 调整重试规则,排除非超时类异常触发重试

修改重试配置,仅对明确的超时类异常重试,新增404等资源不存在异常的排除逻辑:

RetryConfig.custom()
    .maxAttempts(downloadAttempts)
    .retryOnException(e -> (e instanceof DownloadTimeoutException))
    // 新增排除逻辑,资源不存在类异常绝不重试
    .retryOnException(e -> !(e instanceof DownloadResourceNotFoundException))
    .waitDuration(Duration.ofMillis(30))
    .build();

3. 可选优化:添加响应超时控制

如果还是遇到部分服务端挂起连接的问题,可以额外配置setConnectionRequestTimeout,或者使用HttpAsyncResponseConsumer来控制响应的整体读取时长,避免无限等待。

// RequestConfig新增连接请求超时配置
RequestConfig config = RequestConfig.custom()
    .setSocketTimeout(10000)
    .setConnectTimeout(5000)
    .setConnectionRequestTimeout(3000) // 新增,从连接池获取连接的超时时间
    .setRedirectsEnabled(true)
    .setMaxRedirects(3)
    .setStaleConnectionCheckEnabled(false)
    .setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.BASIC))
    .build();

验证效果

优化后,只要服务端返回了404状态码,会立刻触发资源不存在异常,不会进入读取等待逻辑,也不会触发重试,可将无效URL的请求耗时从20秒降低到毫秒级。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 06:57:04