org.apache.http.impl.execchain.RequestAbortedException:请求已中止

时间:2017-03-26 22:19:32

标签: java apache http

当使用apache http客户端从我的Web应用程序向第三方系统进行http调用时,我遇到了一个问题。我使用的是http-core-4.4.4和http-client-4.5.1。 此票证HTTPCORE-446表示已解决死锁问题并正常终止线程并发生异常。有没有人遇到过这个例外,并且对导致这个问题的原因以及如何解决这个问题有任何想法?。

编辑:用于进行http调用的Http代码段

 protected <ResponseObj> run() throws Exception {

    String uri = <target system uri>;
    HttpPost httpPost = new HttpPost(uri);
    final HttpEntity entity = <Built http entity obj>;
    httpPost.setEntity(entity);
    HttpClient client = HttpClientBuilder.create().build();
    try {
        final HttpResponse response = client.execute(httpPost);
        ResponseObj res = processResponse(response);

        return res;

    } catch (Exception e) {

        LOGGER.error(ERROR_CALLING_TARGET, e);
        throw new CustomException(e);
    }
}

异常

org.apache.http.impl.execchain.RequestAbortedException: Request aborted
at     org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:193) ~[httpclient-4.5.1.jar:4.5.1]
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184) ~[httpclient-4.5.1.jar:4.5.1]
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88) ~[httpclient-4.5.1.jar:4.5.1]
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) ~[httpclient-4.5.1.jar:4.5.1]
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184) ~[httpclient-4.5.1.jar:4.5.1]
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82) ~[httpclient-4.5.1.jar:4.5.1]
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107) ~[httpclient-4.5.1.jar:4.5.1]
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:55) ~[httpclient-4.5.1.jar:4.5.1]
at com.netflix.hystrix.HystrixCommand$1.call(HystrixCommand.java:294) [hystrix-core-1.4.26.jar:1.4.26]
at com.netflix.hystrix.HystrixCommand$1.call(HystrixCommand.java:289) [hystrix-core-1.4.26.jar:1.4.26]
at rx.Observable$2.call(Observable.java:162) [rxjava-1.1.1.jar:1.1.1]
at rx.Observable$2.call(Observable.java:154) [rxjava-1.1.1.jar:1.1.1]
at rx.Observable$2.call(Observable.java:162) [rxjava-1.1.1.jar:1.1.1]
at rx.Observable$2.call(Observable.java:154) [rxjava-1.1.1.jar:1.1.1]
at rx.Observable$2.call(Observable.java:162) [rxjava-1.1.1.jar:1.1.1]
at rx.Observable$2.call(Observable.java:154) [rxjava-1.1.1.jar:1.1.1]
at rx.Observable.unsafeSubscribe(Observable.java:8314) [rxjava-1.1.1.jar:1.1.1]
at com.netflix.hystrix.AbstractCommand$5.call(AbstractCommand.java:521) [hystrix-core-1.4.26.jar:1.4.26]
at com.netflix.hystrix.AbstractCommand$5.call(AbstractCommand.java:499) [hystrix-core-1.4.26.jar:1.4.26]
at rx.Observable.unsafeSubscribe(Observable.java:8314) [rxjava-1.1.1.jar:1.1.1]
at rx.internal.operators.OperatorSubscribeOn$1.call(OperatorSubscribeOn.java:94) [rxjava-1.1.1.jar:1.1.1]
at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction$1.call(HystrixContexSchedulerAction.java:56) [hystrix-core-1.4.26.jar:1.4.26]
at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction$1.call(HystrixContexSchedulerAction.java:47) [hystrix-core-1.4.26.jar:1.4.26]
at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction.call(HystrixContexSchedulerAction.java:69) [hystrix-core-1.4.26.jar:1.4.26]
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55) [rxjava-1.1.1.jar:1.1.1]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_51]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_51]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_51]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_51]
at java.lang.Thread.null(Unknown Source) [na:1.8.0_51]
Caused by: java.lang.InterruptedException: null
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.reportInterruptAfterWait(AbstractQueuedSynchronizer.java:2014) ~[na:1.8.0_51]
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2048) ~[na:1.8.0_51]
at org.apache.http.pool.PoolEntryFuture.await(PoolEntryFuture.java:138) ~[httpcore-4.4.4.jar:4.4.4]
at org.apache.http.pool.AbstractConnPool.getPoolEntryBlocking(AbstractConnPool.java:306) ~[httpcore-4.4.4.jar:4.4.4]
at org.apache.http.pool.AbstractConnPool.access$000(AbstractConnPool.java:64) ~[httpcore-4.4.4.jar:4.4.4]
at org.apache.http.pool.AbstractConnPool$2.getPoolEntry(AbstractConnPool.java:192) ~[httpcore-4.4.4.jar:4.4.4]
at org.apache.http.pool.AbstractConnPool$2.getPoolEntry(AbstractConnPool.java:185) ~[httpcore-4.4.4.jar:4.4.4]
at org.apache.http.pool.PoolEntryFuture.get(PoolEntryFuture.java:107) ~[httpcore-4.4.4.jar:4.4.4]
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.leaseConnection(PoolingHttpClientConnectionManager.java:276) ~[httpclient-4.5.1.jar:4.5.1]
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager$1.get(PoolingHttpClientConnectionManager.java:263) ~[httpclient-4.5.1.jar:4.5.1]
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:190) ~[httpclient-4.5.1.jar:4.5.1]
... 32 common frames omitted

1 个答案:

答案 0 :(得分:1)

我刚刚遇到了类似的问题,我想我也可以给出一些解决您问题的提示。

我有一个HttpClient定期调用服务器,事实证明,应答该调用非常慢。调度程序启动请求N + 1时,请求N仍在等待响应。

如果查看堆栈跟踪底部显示的MainClientExec ln190的来源,您会看到ConnectionRequest.get()调用引发了原始的InterruptedException,该InterruptedException被捕获,包装为RequestAbortedException,然后重新抛出。引用ConnectionRequest.get()方法javadoc:

在给定时间内获得连接。该方法将阻塞,直到连接可用,超时到期或连接管理器关闭为止。超时的处理精度为毫秒。 如果在阻塞期间或开始之前调用Cancellable.cancel(),将抛出InterruptedException。

那么,在我们的线程上调用cancel()的东西是什么?在我看来,这似乎是另一个执行相同MainClientExec.execute()方法的线程,可能以相同的方式建立了一个请求。在try-catch块上方仅几行:

final ConnectionRequest connRequest = connManager.requestConnection(route, userToken);
if (execAware != null) {
    if (execAware.isAborted()) {
        connRequest.cancel();
        throw new RequestAbortedException("Request aborted");
    } else {
        execAware.setCancellable(connRequest);
    }
}

我的猜测是,如果此代码仍在进行中,则会取消上一个HTTP调用。

因此,在我的情况下,根本问题是服务器运行缓慢(需要花几分钟时间进行响应)。我的解决方案是设置连接并请求超时值。默认情况下,没有为HttpClient设置超时,您必须手动设置它。 See this answer for a working example on how to do this.现在,我的HTTP请求在触发下一个计划的调用之前遇到超时。当服务器响应缓慢时,我仍然会出错,但是超时异常更容易出错。