Использование Apache HttpClient, как установить TIMEOUT на запрос и ответ
Мне нужно установить тайм-аут для запроса Http, который мы делаем для службы (а не веб-службы). Мы используем HTTP-клиент Apache. Я добавил эти 2 строки кода, чтобы установить время ожидания по запросу и ответ на эту услугу.
HttpConnectionParams.setConnectionTimeout(params, 10000);
HttpConnectionParams.setSoTimeout(params, 10000);
1) В настоящее время я установил 10 секунд как тайм-аут, так как я вижу ответ, исходящий от службы почти мгновенно. Должен ли я увеличивать или уменьшать сроки?
2) Что произойдет, когда ответ займет более 10 секунд? Будет ли это исключение и какое это исключение? Есть ли что-то еще, что мне нужно добавить, чтобы установить тайм-аут в приведенном ниже коде.
public HashMap<String, Object> getJSONData(String url) throw Exception{
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpParams params = httpClient.getParams();
HttpConnectionParams.setConnectionTimeout(params, 10000);
HttpConnectionParams.setSoTimeout(params, 10000);
HttpHost proxy = new HttpHost(getProxy(), getProxyPort());
ConnRouteParams.setDefaultProxy(params, proxy);
URI uri;
InputStream data = null;
try {
uri = new URI(url);
HttpGet method = new HttpGet(uri);
HttpResponse response = httpClient.execute(method);
data = response.getEntity().getContent();
}
catch (Exception e) {
e.printStackTrace();
}
Reader r = new InputStreamReader(data);
HashMap<String, Object> jsonObj = (HashMap<String, Object>) GenericJSONUtil.fromJson(r);
return jsonObj;
}
Ответы
Ответ 1
Исключения, которые вы увидите, будут ConnectTimeoutException
и SocketTimeoutException
. Фактические значения тайм-аута, которые вы используете, должны быть максимальным временем ожидания вашего приложения. Важное примечание о тайм-ауте чтения заключается в том, что оно соответствует таймауту в считываемом сокете. Таким образом, это не время, позволяющее получить полный ответ, а время, указанное для одного сокета. Так что если есть 4 сокета, каждый из которых занимает 9 секунд, ваше общее время чтения составляет 9 * 4 = 36 секунд.
Если вы хотите указать общее время получения ответа (включая соединение и общее время чтения), вы можете обернуть вызов в потоке и использовать для этого тайм-аут потока. Например, я обычно делаю что-то вроде этого:
Future<T> future = null;
future = pool.submit(new Callable<T>() {
public T call() {
return executeImpl(url);
}
});
try {
return future.get(10, TimeUnit.SECONDS);
}
catch (InterruptedException e) {
log.warn("task interrupted", name);
}
catch (ExecutionException e) {
log.error(name + " execution exception", e);
}
catch (TimeoutException e) {
log.debug("future timed out", name);
}
Некоторые предположения, сделанные в приведенном выше коде: 1) это функция с параметром url, 2) она в классе с переменной имени, 3) журнал - это экземпляр log4j, а 4) пул - это некоторый исполнитель пула потоков. Обратите внимание, что даже если вы используете тайм-аут потока, вы также должны указать время ожидания подключения и сокета на HttpClient, чтобы медленные запросы не потребляли ресурсы в пуле потоков. Также обратите внимание, что я использую пул потоков, потому что, как правило, я использую это в веб-службе, поэтому пул потоков распределяется по цепочке потоков tomcat. Окружение может быть другим, и вы можете просто создать новый поток для каждого вызова.
Кроме того, я обычно вижу таймауты, установленные через функции-члены params, например:
params.setConnectionTimeout(10000);
params.setSoTimeout(10000);
Но, возможно, ваш синтаксис работает (не уверен).
Ответ 2
Я предполагаю, что многие люди приходят сюда из-за названия и потому, что API HttpConnectionParams
устарел.
Используя последнюю версию HTTP-клиента Apache, вы можете установить эти таймауты с помощью параметров запроса:
HttpPost request = new HttpPost(url);
RequestConfig requestConfig = RequestConfig.custom()
.setSocketTimeout(TIMEOUT_MILLIS)
.setConnectTimeout(TIMEOUT_MILLIS)
.setConnectionRequestTimeout(TIMEOUT_MILLIS)
.build();
request.setConfig(requestConfig);
В качестве альтернативы вы также можете установить это при создании своего HTTP-клиента, используя API-интерфейс Builder для HTTP-клиента, но вам также потребуется создать настраиваемый диспетчер соединений с конфигурацией сокетов.
Файл конфигурации является отличным ресурсом, чтобы узнать, как настроить HTTP-клиент Apache.