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 -

  1. can interrupt asyncresttemplate call if http request taking long? calling cancel on future in above code in executesync 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 interrupt resttemplate calls not sure on asyncresttemplate whether can or not. if let's can interrupt asyncresttemplate calls, doing right interrupt http calls? or there better/cleaner way this? or need worry cancelling http request asyncresttemplate 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?

  2. also doing right thing in catch block of interruptedexception in executesync method? if not, what's right way deal that. , need deal interruptedexception @ in case?
  3. 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

Popular posts from this blog

javascript - AngularJS custom datepicker directive -

javascript - jQuery date picker - Disable dates after the selection from the first date picker -