2012-03-26 4 views
24

Мне нужно установить время ожидания запроса Http для службы (а не веб-службы). Мы используем HTTP-клиент Apache. Я добавил эти 2 строки кода, чтобы установить время ожидания по запросу и ответ на эту услугу.Использование Apache HttpClient, как установить TIMEOUT на запрос и ответ

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; 
} 

ответ

31

Исключения вы увидите будет 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) log - это экземпляр log4j, а 4) пул - это исполнитель пула потоков. Обратите внимание, что даже если вы используете тайм-аут потока, вы также должны указать время ожидания подключения и сокета на HttpClient, чтобы медленные запросы не потребляли ресурсы в пуле потоков. Также обратите внимание, что я использую пул потоков, потому что, как правило, я использую это в веб-службе, поэтому пул потоков распределяется по цепочке потоков tomcat. Вы окружение может быть другим, и вы можете предпочесть просто порождать новый поток для каждого вызова.

Кроме того, я обычно вижу таймауты, установленные с помощью функций-членов в Params, как это:

params.setConnectionTimeout(10000); 
params.setSoTimeout(10000); 

Но, возможно, ваш синтаксис работает хорошо (не уверен).

+0

Что мне нужно установить/добавить, если мне нужно дозвониться до полного ответа? – pushya

+0

Не могли бы вы объяснить, что вы подразумеваете под 4-мя сокетами? Если они считываются 4 сокета, тогда будет 4 разных запроса, связанных с этим чтением. – pushya

+2

нет, ответ может прийти в кусках.Если вы посмотрите на любой код сокета низкого уровня, вы увидите, что 'read()' происходит в цикле while, а возвращаемое значение 'read()' - это количество прочитанных байтов. Нет требования, чтобы весь ответ приходил в одно считывание сокета. Я уточню свой ответ, чтобы включить более подробную информацию. – Kevin

47

Я предполагаю, что многие люди приходят сюда из-за названия и потому, что API HttpConnectionParams устарел.

Используя последнюю версию Client Apache HTTP, вы можете установить эти таймауты с помощью запроса Params:

HttpPost request = new HttpPost(url); 

RequestConfig requestConfig = RequestConfig.custom() 
    .setSocketTimeout(TIMEOUT_MILLIS) 
    .setConnectTimeout(TIMEOUT_MILLIS) 
    .setConnectionRequestTimeout(TIMEOUT_MILLIS) 
    .build(); 

request.setConfig(requestConfig); 

В качестве альтернативы, вы можете также установить это при создании HTTP клиента, используя строитель API для HTTP, но вам также понадобится создать настраиваемый диспетчер соединений с настраиваемой конфигурацией сокета.

configuration example file - отличный ресурс, чтобы узнать, как настроить Apache HTTP Client.

Смежные вопросы