2012-03-26 8 views
24

Muszę ustawić limit czasu dla żądania HTTP do usługi (nie do usługi internetowej). Używamy klienta HTTP Apache. Dodałem te 2 linie kodu, aby ustawić czas na żądanie i odpowiedź na usługę.Używanie Apache HttpClient do ustawiania CZASU TIMEOUT na żądanie i odpowiedzi

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

1) Obecnie ustawiłem 10 sekund jako czas oczekiwania, ponieważ widzę odpowiedź przychodzącą z usługi niemal natychmiast. Czy powinienem zwiększyć lub zmniejszyć czas?

2) Co się stanie, gdy reakcja zajmie więcej niż 10 sekund? Czy wyrzuci wyjątek i jaki będzie to wyjątek? Czy jest coś jeszcze, co muszę dodać, aby ustawić czas w poniższym kodzie.

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

Odpowiedz

31

Wyjątkiem będzie widać będzie ConnectTimeoutException i SocketTimeoutException. Rzeczywiste wartości limitu czasu, których używasz, powinny być maksymalnym czasem, jaki aplikacja chce czekać. Ważną informacją na temat limitu czasu odczytu jest to, że odpowiada on przekroczeniu limitu czasu w czytanym gnieździe. Nie czas na pełną odpowiedź, ale raczej na czas przeznaczony na odczyt pojedynczego gniazda. Więc jeśli istnieją 4 odczyty gniazd, z których każde zajmuje 9 sekund, całkowity czas odczytu wynosi 9 * 4 = 36 sekund.

Jeśli chcesz określić łączny czas na odpowiedź (łącznie z łącznym i całkowitym czasem odczytu), możesz zawinąć wywołanie w wątku i użyć do tego limitu czasu wątku. Na przykład, zwykle zrobić coś takiego:

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

pewnych założeń zawartych w powyższym kodzie, są: 1) Jest to funkcja z parametrem zawartości, 2) jest w klasie z nazwy zmiennej, 3) log jest instancją log4j, a 4) pulą jest pewnym executorem puli wątków. Zauważ, że nawet jeśli używasz limitu czasu wątku, powinieneś również określić limit czasu połączenia i gniazda w HttpClient, aby powolne żądania nie pochłaniały zasobów w puli wątków. Zauważ też, że używam puli wątków, ponieważ zazwyczaj używam tego w usłudze internetowej, aby pula wątków była współdzielona przez kilka wątków tomcat. Twoje otoczenie może być inne i możesz preferować odrodzenie nowego wątku dla każdego połączenia.

Także, ja zazwyczaj zobaczyć timeoutów określone poprzez funkcje Członka params coś takiego:

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

Ale może składnia działa tak samo (nie jestem pewien).

+0

Co muszę ustawić/dodać, jeśli muszę zezwolić na pełny czas reakcji – pushya

+0

Czy możesz wyjaśnić, co masz na myśli mówiąc o 4 gniazdach? Jeśli są czytane w 4 gniazdach, to z tym odczytem będzie 4 różne żądanie. – pushya

+2

Nie, odpowiedź może być podzielona na fragmenty.Jeśli spojrzeć na jakiegokolwiek kodu niskiego poziomu gniazda zobaczysz, że 'read()' dzieje się w pętli while, a wartość zwrot 'read()' jest liczba odczytanych bajtów. Nie ma wymogu, aby cała odpowiedź przychodziła w jednym czytanym gnieździe. Zaktualizuję moją odpowiedź, by podać więcej szczegółów. – Kevin

47

Zgaduję, że wielu ludzi przybyło tutaj z powodu tytułu i dlatego, że API HttpConnectionParams jest przestarzałe.

Korzystanie z najnowszej wersji klienta HTTP Apache, można ustawić te limity czasu używając params żądanie:

HttpPost request = new HttpPost(url); 

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

request.setConfig(requestConfig); 

Alternatywnie, można również ustawić to podczas tworzenia klienta HTTP, używając API Builder dla Klient HTTP, ale musisz także utworzyć niestandardowy menedżer połączeń z niestandardową konfiguracją gniazd.

Urządzenie configuration example file jest doskonałym źródłem informacji o tym, jak skonfigurować klienta HTTP Apache.

Powiązane problemy