我在我的一個庫中使用RestTemplate
作爲我的HttpClient
。我不確定我是否在多線程環境中正確使用它,因爲我的庫將在多線程環境下在非常繁重的負載下使用,因此它必須非常快速。如何在多線程應用程序中有效使用RestTemplate?
下面是我的DataClient類:
public class DataClient implements Client {
private RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory());
private ExecutorService executor = Executors.newFixedThreadPool(10);
// for synchronous call
@Override
public DataResponse executeSync(DataKey key) {
DataResponse dataResponse = null;
Future<DataResponse> future = null;
try {
future = executeAsync(key);
dataResponse = future.get(key.getTimeout(), TimeUnit.MILLISECONDS);
} catch (TimeoutException ex) {
dataResponse = new DataResponse(null, DataErrorEnum.TIMEOUT, DataStatusEnum.ERROR);
future.cancel(true);
} catch (Exception ex) {
dataResponse = new DataResponse(null, DataErrorEnum.CLIENT_ERROR, DataStatusEnum.ERROR);
}
return dataResponse;
}
//for asynchronous call
@Override
public Future<DataResponse> executeAsync(DataKey key) {
Future<DataResponse> future = null;
Task task = new Task(key, restTemplate);
future = executor.submit(task);
return future;
}
// does this looks right?
private ClientHttpRequestFactory clientHttpRequestFactory() {
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
// setting 2000 ms as the default timeout for each Http Request
RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(2000).setConnectTimeout(2000)
.setSocketTimeout(2000).setStaleConnectionCheckEnabled(false).build();
SocketConfig socketConfig = SocketConfig.custom().setSoKeepAlive(true).setTcpNoDelay(true).build();
PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager();
poolingHttpClientConnectionManager.setMaxTotal(800);
poolingHttpClientConnectionManager.setDefaultMaxPerRoute(700);
CloseableHttpClient httpClientBuilder = HttpClientBuilder.create()
.setConnectionManager(poolingHttpClientConnectionManager).setDefaultRequestConfig(requestConfig)
.setDefaultSocketConfig(socketConfig).build();
requestFactory.setHttpClient(httpClientBuilder);
return requestFactory;
}
}
將執行實際任務的簡單類:
public class Task implements Callable<DataResponse> {
private final DataKey key;
private final RestTemplate restTemplate;
public Task(DataKey key, RestTemplate restTemplate) {
this.key = key;
this.restTemplate = restTemplate;
}
@Override
public DataResponse call() {
DataResponse dataResponse = null;
String response = null;
try {
String url = createURL();
response = restTemplate.getForObject(url, String.class);
dataResponse = new DataResponse(response, DataErrorEnum.OK, DataStatusEnum.SUCCESS);
} catch (RestClientException ex) {
dataResponse = new DataResponse(null, DataErrorEnum.SERVER_DOWN, DataStatusEnum.ERROR);
} catch (Exception ex) {
dataResponse = new DataResponse(null, DataErrorEnum.CLIENT_ERROR, DataStatusEnum.ERROR);
}
return dataResponse;
}
}
而下面是我廠裏面我是用創造DataClient的一個實例,其意味着,它也將有單個實例RestTemplate
。
public class DataClientFactory {
private DataClientFactory() {}
private static class ClientHolder {
private static final DataClient INSTANCE = new DataClient();
}
public static Client getInstance() {
return ClientHolder.INSTANCE;
}
}
這是這樣,我會打個電話來獲取數據:
DataResponse response = DataClientFactory.getInstance().executeSync(dataKey);
現在的問題是 - 我不知道我是否正確使用RestTemplate
與HttpComponentsClientHttpRequestFactory
。我是否需要PoolingHttpClientConnectionManager
以及RestTemplate
?
我的主要目標是在多線程環境中高效地使用RestTemplate
。由於我的圖書館將在非常沉重的負荷下使用,因此它必須非常快速。由於負載很重,我看到很多TIME_WAIT連接,所以我添加了clientHttpRequestFactory()
方法與RestTemplate
一起使用。
我已經在我的問題中創建了一個'RestTemplate'實例嗎?我稍微更新了它,告訴我如何使用DataClient類。所以我爲所有調用使用相同的HTTP屬性。你能再看看我的問題嗎? – john
我看到你正在爲同步調用創建一個新線程。基本上浪費了在不需要時創建新線程的成本。請看http://stackoverflow.com/a/29447961/2776345。 –