Ho una libreria che viene utilizzata dal cliente e stanno passando l'oggetto DataRequest
che ha userid
, timeout
e alcuni altri campi in esso. Ora uso questo oggetto DataRequest
per creare un URL e poi faccio una chiamata HTTP usando RestTemplate
e il mio servizio restituisce una risposta JSON che io uso per creare un oggetto DataResponse
e restituire a questo oggetto DataResponse
.Come impostare RequestConfiguration per richiesta usando RestTemplate?
Di seguito è riportata la mia classe DataClient
utilizzata dal cliente passando l'oggetto DataRequest
. Sto utilizzando il valore di timeout passato dal cliente in DataRequest
per timeout della richiesta se impiega troppo tempo nel metodo getSyncData
.
public class DataClient implements Client {
private final RestTemplate restTemplate = new RestTemplate();
private final ExecutorService service = Executors.newFixedThreadPool(10);
// this constructor will be called only once through my factory
// so initializing here
public DataClient() {
try {
restTemplate.setRequestFactory(clientHttpRequestFactory());
} catch (Exception ex) {
// log exception
}
}
@Override
public DataResponse getSyncData(DataRequest key) {
DataResponse response = null;
Future<DataResponse> responseFuture = null;
try {
responseFuture = getAsyncData(key);
response = responseFuture.get(key.getTimeout(), key.getTimeoutUnit());
} catch (TimeoutException ex) {
response = new DataResponse(DataErrorEnum.CLIENT_TIMEOUT, DataStatusEnum.ERROR);
responseFuture.cancel(true);
// logging exception here
}
return response;
}
@Override
public Future<DataResponse> getAsyncData(DataRequest key) {
DataFetcherTask task = new DataFetcherTask(key, restTemplate);
Future<DataResponse> future = service.submit(task);
return future;
}
// how to set socket timeout value by using `key.getSocketTimeout()` instead of using hard coded 400
private ClientHttpRequestFactory clientHttpRequestFactory() {
HttpComponentsClientHttpRequestFactory requestFactory =
new HttpComponentsClientHttpRequestFactory();
RequestConfig requestConfig =
RequestConfig.custom().setConnectionRequestTimeout(400).setConnectTimeout(400)
.setSocketTimeout(400).setStaleConnectionCheckEnabled(false).build();
SocketConfig socketConfig =
SocketConfig.custom().setSoKeepAlive(true).setTcpNoDelay(true).build();
PoolingHttpClientConnectionManager poolingHttpClientConnectionManager =
new PoolingHttpClientConnectionManager();
poolingHttpClientConnectionManager.setMaxTotal(300);
poolingHttpClientConnectionManager.setDefaultMaxPerRoute(200);
CloseableHttpClient httpClientBuilder =
HttpClientBuilder.create().setConnectionManager(poolingHttpClientConnectionManager)
.setDefaultRequestConfig(requestConfig).setDefaultSocketConfig(socketConfig).build();
requestFactory.setHttpClient(httpClientBuilder);
return requestFactory;
}
}
DataFetcherTask
classe:
public class DataFetcherTask implements Callable<DataResponse> {
private final DataRequest key;
private final RestTemplate restTemplate;
public DataFetcherTask(DataRequest key, RestTemplate restTemplate) {
this.key = key;
this.restTemplate = restTemplate;
}
@Override
public DataResponse call() throws Exception {
// In a nutshell below is what I am doing here.
// 1. Make an url using DataRequest key.
// 2. And then execute the url RestTemplate.
// 3. Make a DataResponse object and return it.
}
}
clienti all'interno della nostra società utilizzerà la mia libreria in questo modo, come mostrato di seguito utilizzando mia fabbrica nella loro base di codice -
// if they are calling `getSyncData()` method
DataResponse response = DataClientFactory.getInstance().getSyncData(key);
// and if they want to call `getAsyncData()` method
Future<DataResponse> response = DataClientFactory.getInstance().getAsyncData(key);
Io sono l'attuazione sync call as async + waiting
dal momento che voglio strozzarli con il numero di thread altrimenti possono bombardare il nostro servizio senza alcun controllo.
problema dichiarazione: -
ho intenzione di aggiungere un'altra variabile timeout chiamato socket timeout
nella mia classe DataRequest
e voglio utilizzare tale valore variabile (key.getSocketTimeout())
nel mio metodo clientHttpRequestFactory()
invece di utilizzare rigido codificato 400 valore. Qual è il modo migliore ed efficace per farlo?
In questo momento sto usando Inversion of Control
e passando RestTemplate
in un costruttore per condividere il RestTemplate
tra tutti i miei oggetti Task. Sono confuso ora come utilizzare il valore key.getSocketTimeout()
nel mio metodo clientHttpRequestFactory()
. Penso che questa sia principalmente la domanda di design su come usare efficientemente RestTemplate
in modo da poter usare il valore key.getSocketTimeout()
nel mio metodo clientHttpRequestFactory()
.
Ho semplificato il codice in modo che l'idea diventi chiara cosa sto cercando di fare e io sono su Java 7. L'utilizzo di ThreadLocal
è l'unica opzione che ho qui o c'è un modo migliore e ottimizzato?
Grazie per il tuo suggerimento, quindi quali sono le opzioni che ho che posso utilizzare qui? qualche idea? – user1950349
@ user1950349 AFAICS le altre opzioni saranno peggiori rispetto all'utilizzo di un ThreadLocal. –
Vedo. Puoi fornire un esempio di come sarà il mio codice con 'ThreadLocal'. Posso fare alcuni test di carico e vedere se ha un impatto sulle prestazioni o meno. Non ho ancora lavorato con ThreadLocal e leggere documenti mi sta causando più confusione, quindi non sono sicuro di come posso usarlo nella mia soluzione. – user1950349