java - How to cancel AsyncRestTemplate HTTP request if they are taking too much time? -
since starting, confuse of how deal interruptedexception , how cancel http request if taking time. have library in have provided 2 methods, sync , async our customer. can call whichever method feel right purpose.
- executesync() - waits until have result, returns result.
- executeasync() - returns future can processed after other things done, if needed.
they pass datakey
object has user id , timeout value in it. figure out machine call basis on user id , create url machine , make http call url using asyncresttemplate , send response them basis on whether successful or not.
i using exchange method of asyncresttemplate
returns listenablefuture
, wanted have async non blocking architecture nio based client connections request uses non blocking io that's why went asyncresttemplate
. approach sounds right problem definition? library used in production under heavy load.
below interface:
public interface client { // synchronous public dataresponse executesync(datakey key); // asynchronous public listenablefuture<dataresponse> executeasync(datakey key); }
and below implementation of interface:
public class dataclient implements client { // using spring 4 asyncresttemplate private final asyncresttemplate resttemplate = new asyncresttemplate(); // 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) { // need catch interruptedexception here , interrupt thread? thread.currentthread().interrupt(); // need throw runtimeexception @ 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 tasks got timed out don't take resources? } catch (exception ex) { datalogging.logevents(ex, dataerrorenum.error_client, keys); response = new dataresponse(null, dataerrorenum.error_client, datastatusenum.error); } return response; } // 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 original request responsefuture.addlistener(new runnable() { @override public void run() { if (responsefuture.iscancelled()) { orig.cancel(false); // keeping false } } }, moreexecutors.directexecutor()); return responsefuture; } }
and customer calling code -
// if calling executesync() method dataresponse response = dataclientfactory.getinstance().executesync(datakey); // , if want call executeasync() method future<dataresponse> response = dataclientfactory.getinstance().executeasync(datakey);
now question -
can interrupt
asyncresttemplate
call if http request taking long? callingcancel
onfuture
in above code inexecutesync
method not sure how verify make sure doing should? want propagate cancellation original future, can cancel corresponding http request (which want save resources) that's why have added listener in executeasync method. believe, cannot interruptresttemplate
calls not sure onasyncresttemplate
whether can or not. if let's can interruptasyncresttemplate
calls, doing right interrupt http calls? or there better/cleaner way this? or need worry cancelling http requestasyncresttemplate
current design?// propagate cancellation original request responsefuture.addlistener(new runnable() { @override public void run() { if (responsefuture.iscancelled()) { orig.cancel(false); // keeping false } } }, moreexecutors.directexecutor());
with current setup, can see throwing cancellationexception of times (not everytime)- mean http request cancelled then?
- also doing right thing in catch block of
interruptedexception
inexecutesync
method? if not, what's right way deal that. , need dealinterruptedexception
@ in case? - is true default
asyncresttamplete
uses blocking calls , request per thread? if yes, there way have nio based client connections in current setup?
any explanations/code suggestions of great help.
first of all, why using settablefuture? why can't return listenablefuture returned asyncresttemplate?
1. can interrupt asyncresttemplate call if http request taking long?
of course do! need call future.cancel
method. method interrupt execution of internal resttemplate asyncresttemplate using.
2. doing right thing in catch block of interruptedexception in executesync method?
as phil , danilo have said, don't need interrupt current thread within interruptedexception catch block. whatever need when execution of request must canceled.
in fact, recommend create method handles behaviour, handleinterruption, , use method both timeoutexception
, interruptedexception
.
3. true default asyncresttamplete uses blocking calls , request per thread?
yes. default constructor of asyncresttamplete
internally using simpleclienthttprequestfactory
, simpleasynctaskexecutor
.
this taskexecutor starts threat every task, , never reuse threads, it's inefficient:
* taskexecutor implementation fires new thread each task, * executing asynchronously. * * supports limiting concurrent threads through "concurrencylimit" * bean property. default, number of concurrent threads unlimited. * * note: implementation not reuse threads! consider * thread-pooling taskexecutor implementation instead, in particular * executing large number of short-lived tasks. *
i recommend use configuration of asyncresttemplate.
you should use constructor of asyncresttemplate uses taskexecutor:
public asyncresttemplate(asynclistenabletaskexecutor taskexecutor)
for instance:
asyncresttemplate template = new asyncresttemplate(new concurrenttaskexecutor(executors.newcachedthreadpool()));
this executorservice (executors.newcachedthreadpool()) creates new threads needed, reuse constructed threads when available.
or better, can use requestfactory. instance, can use httpcomponentsasyncclienthttprequestfactory
, internally uses nio, calling proper constructor of asyncresttemplate:
new asyncresttemplate(new httpcomponentsasyncclienthttprequestfactory())
don't forget internal behaviour of asyncresttemplate depend on how create object.
Comments
Post a Comment