如果它们花费太多时间,如何取消AsyncRestTemplate HTTP请求?
从开始,我总是对如何处理DisstrutedException以及如何在花费太多时间时正确取消http请求感到困惑。我有一个库,其中我为客户提供了两种方法,sync和async。他们可以调用他们认为适合其目的的任何方法。
- executeSync() - 等到我有一个结果,返回结果。
- executeAsync() - 立即返回一个 Future,如果需要,可以在完成其他操作后进行处理。
他们将传递包含用户 ID 和超时值的对象。我们将根据用户ID确定要调用哪台计算机,然后使用该计算机创建一个URL,我们将使用AsyncRestTemplate对URL进行http调用,然后根据响应是否成功将其发送回他们。DataKey
我正在使用交换方法,其中返回a,并且我希望具有基于NIO的客户端连接的异步非阻塞架构,以便该请求使用非阻塞IO,这就是我使用的原因。此方法听起来适合我的问题定义吗?此库将在非常重的负载下用于生产。AsyncRestTemplate
ListenableFuture
AsyncRestTemplate
以下是我的界面:
public interface Client {
// for synchronous
public DataResponse executeSync(DataKey key);
// for asynchronous
public ListenableFuture<DataResponse> executeAsync(DataKey key);
}
以下是我对接口的实现:
public class DataClient implements Client {
// using spring 4 AsyncRestTemplate
private final AsyncRestTemplate restTemplate = new AsyncRestTemplate();
// for synchronous
@Override
public DataResponse executeSync(DataKey keys) {
Future<DataResponse> responseFuture = executeAsync(keys);
DataResponse response = null;
try {
response = responseFuture.get(keys.getTimeout(), TimeUnit.MILLISECONDS);
} catch (InterruptedException ex) {
// do we need to catch InterruptedException here and interrupt the thread?
Thread.currentThread().interrupt();
// also do I need throw this RuntimeException at all?
throw new RuntimeException("Interrupted", ex);
} catch (TimeoutException ex) {
DataLogging.logEvents(ex, DataErrorEnum.CLIENT_TIMEOUT, keys);
response = new DataResponse(null, DataErrorEnum.CLIENT_TIMEOUT, DataStatusEnum.ERROR);
responseFuture.cancel(true); // terminating the tasks that got timed out so that they don't take up the resources?
} catch (Exception ex) {
DataLogging.logEvents(ex, DataErrorEnum.ERROR_CLIENT, keys);
response = new DataResponse(null, DataErrorEnum.ERROR_CLIENT, DataStatusEnum.ERROR);
}
return response;
}
// for asynchronous
@Override
public ListenableFuture<DataResponse> executeAsync(final DataKey keys) {
final SettableFuture<DataResponse> responseFuture = SettableFuture.create();
final org.springframework.util.concurrent.ListenableFuture orig =
restTemplate.exchange(createURL(keys), HttpMethod.GET, keys.getEntity(), String.class);
orig.addCallback(
new ListenableFutureCallback<ResponseEntity<String>>() {
@Override
public void onSuccess(ResponseEntity<String> result) {
responseFuture.set(new DataResponse(result.getBody(), DataErrorEnum.OK,
DataStatusEnum.SUCCESS));
}
@Override
public void onFailure(Throwable ex) {
DataLogging.logErrors(ex, DataErrorEnum.ERROR_SERVER, keys);
responseFuture.set(new DataResponse(null, DataErrorEnum.ERROR_SERVER,
DataStatusEnum.ERROR));
}
});
// propagate cancellation back to the original request
responseFuture.addListener(new Runnable() {
@Override public void run() {
if (responseFuture.isCancelled()) {
orig.cancel(false); // I am keeping this false for now
}
}
}, MoreExecutors.directExecutor());
return responseFuture;
}
}
客户将从他们的代码中这样调用 -
// if they are calling executeSync() method
DataResponse response = DataClientFactory.getInstance().executeSync(dataKey);
// and if they want to call executeAsync() method
Future<DataResponse> response = DataClientFactory.getInstance().executeAsync(dataKey);
现在的问题是——
-
如果 http 请求花费的时间太长,我们可以中断调用吗?我实际上正在调用我上面的代码中的方法,但我不确定如何验证它以确保它正在做它应该做的事情?我想将取消传播回原来的未来,这样我就可以取消相应的http请求(我可能想这样做以节省资源),这就是为什么我在exactAsync方法中添加了一个侦听器。我相信,我们不能打断电话,但不确定我们是否可以这样做。如果假设我们可以中断调用,那么我是否做对了一切来中断http调用?或者有没有更好/更清洁的方法可以做到这一点?或者我甚至需要担心使用我当前的设计取消Http请求吗?
AsyncRestTemplate
cancel
future
executeSync
RestTemplate
AsyncRestTemplate
AsyncRestTemplate
AsyncRestTemplate
// propagate cancellation back to the original request responseFuture.addListener(new Runnable() { @Override public void run() { if (responseFuture.isCancelled()) { orig.cancel(false); // I am keeping this false for now } } }, MoreExecutors.directExecutor());
使用当前的设置,我可以看到它在某些时候(不是每次)抛出UnjectException - 这是否意味着我的HTTP请求被取消了?
- 另外,我是否在捕获块的方法中做了正确的事情?如果没有,那么处理这个问题的正确方法是什么。在我的情况下,我需要处理吗?
InterruptedException
executeSync
InterruptedException
- 默认情况下,每个线程使用阻塞调用和请求,这是真的吗?如果是,那么有没有办法在我当前的设置中建立基于NIO的客户端连接?
AsyncRestTamplete
任何解释/代码建议都将有很大的帮助。