use*_*349 12 java spring multithreading resttemplate apache-httpclient-4.x
我有一个正在使用的客户库和传入DataRequest
对象拥有userid
,timeout
并且在它的一些其他领域.现在我使用这个DataRequest
对象创建一个URL,然后我使用了一个HTTP调用RestTemplate
,我的服务返回一个JSON响应,我用它来创建一个DataResponse
对象并将这个DataResponse
对象返回给它们.
以下是DataClient
客户通过将DataRequest
对象传递给我的类.DataRequest
如果在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;
}
}
Run Code Online (Sandbox Code Playgroud)
DataFetcherTask
类:
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.
}
}
Run Code Online (Sandbox Code Playgroud)
我们公司内的客户将在我们的代码库中使用我的工厂,如下所示使用我的库 -
// 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);
Run Code Online (Sandbox Code Playgroud)
我正在实施,sync call as async + waiting
因为我想用线程数限制它们,否则他们可以在没有任何控制的情况下轰炸我们的服务.
问题陈述:-
我将添加socket timeout
在我的DataRequest
类中调用的另一个超时变量,我想(key.getSocketTimeout())
在我的clientHttpRequestFactory()
方法中使用该变量值,而不是使用硬编码的400值.这样做的最佳和最有效的方法是什么?
现在我正在使用Inversion of Control
并传入RestTemplate
一个构造函数来共享RestTemplate
我所有的Task对象.我现在很困惑如何key.getSocketTimeout()
在我的clientHttpRequestFactory()
方法中使用值.我认为这主要是如何在RestTemplate
这里有效使用的设计问题,以便我可以key.getSocketTimeout()
在我的clientHttpRequestFactory()
方法中使用值.
我已经简化了代码,以便想法清楚我想要做什么,我在Java 7.使用ThreadLocal
是我在这里的唯一选择还是有更好的优化方式?
ThreadLocal 是一种传递动态值的方法,通常您可以通过方法属性传递动态值,但您使用的 API 不能/不想更改。
您可以在线程堆栈中的某个级别设置 ThreadLocal(可能是包含多个值的数据结构),并且可以在堆栈中进一步使用它。
这是最好的方法吗?不,您确实应该将值传递到方法调用链上,但有时这是不切实际的。
你能提供一个例子来说明我的代码在 ThreadLocal 中的样子吗
你可能会从
static final ThreadLocal<Long> SOCKET_TIMEOUT = new ThreadLocal<>();
Run Code Online (Sandbox Code Playgroud)
要设置它,你可以这样做
SOCKET_TIMEOUT .set(key.getSocketTimeout());
Run Code Online (Sandbox Code Playgroud)
并获得你能做到的价值
long socketTimeout = SOCKET_TIMEOUT.get();
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1580 次 |
最近记录: |