Chciałbym wykonać BIT (testy wbudowane) na kilka serwerów w mojej chmurze. Potrzebuję, aby żądanie zakończyło się niepowodzeniem po długim czasie oczekiwania
Jak mam to zrobić w Javie?
Wydaje się, że próbowanie czegoś takiego jak poniżej nie działa.
public class TestNodeAliveness {
public static NodeStatus nodeBIT(String elasticIP) throws ClientProtocolException, IOException {
HttpClient client = new DefaultHttpClient();
client.getParams().setIntParameter("http.connection.timeout", 1);
HttpUriRequest request = new HttpGet("http://192.168.20.43");
HttpResponse response = client.execute(request);
System.out.println(response.toString());
return null;
}
public static void main(String[] args) throws ClientProtocolException, IOException {
nodeBIT("");
}
}
- EDYTUJ: wyjaśnij, która biblioteka jest używana -
Używam httpclient z Apache, tutaj jest odpowiednia sekcja pom.xml
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.0.1</version>
<type>jar</type>
</dependency>
java
http
timeout
network-protocols
Maxim Veksler
źródło
źródło
Odpowiedzi:
import org.apache.http.client.HttpClient; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; ... // set the connection timeout value to 30 seconds (30000 milliseconds) final HttpParams httpParams = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(httpParams, 30000); client = new DefaultHttpClient(httpParams);
źródło
Jeśli używasz klienta HTTP w wersji 4.3 lub nowszej, powinieneś używać tego:
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30 * 1000).build(); HttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).build();
źródło
SocketTimeout
. Ponadto, czy „default” oznacza, że jest to wartość domyślna dla wszystkiego,HttpClient
co funkcjaHttpClientBuilder
from create () da za pośrednictwembuild()
metody? Czy tylko te, które przechodząsetDefaultRequestConfig(requestConfig)
? Czy mam sens?HttpParams jest przestarzałe w nowej bibliotece Apache HTTPClient. Korzystanie z kodu dostarczonego przez Laz prowadzi do ostrzeżeń o wycofaniu.
Proponuję zamiast tego użyć RequestConfig w Twojej instancji HttpGet lub HttpPost:
final RequestConfig params = RequestConfig.custom().setConnectTimeout(3000).setSocketTimeout(3000).build(); httpPost.setConfig(params);
źródło
RequestConfig
w everyHttpPost
a ustawieniem go jako domyślnym wHttpClient
?Wygląda na to, że używasz HttpClient API, o którym nic nie wiem, ale możesz napisać coś podobnego do tego, używając podstawowej Javy.
try { HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection(); con.setRequestMethod("HEAD"); con.setConnectTimeout(5000); //set timeout to 5 seconds return (con.getResponseCode() == HttpURLConnection.HTTP_OK); } catch (java.net.SocketTimeoutException e) { return false; } catch (java.io.IOException e) { return false; }
źródło
Okazało się, że ustawienie limitu czasu
HttpConnectionParams
iHttpConnectionManager
nie rozwiązało naszej sprawy. Jesteśmy ograniczeni do używaniaorg.apache.commons.httpclient
wersji 3.0.1.Skończyło się na użyciu
java.util.concurrent.ExecutorService
do monitorowaniaHttpClient.executeMethod()
połączenia.Oto mały, samodzielny przykład
import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.methods.EntityEnclosingMethod; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.methods.multipart.FilePart; import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity; import org.apache.commons.httpclient.methods.multipart.Part; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.concurrent.*; /** * @author Jeff Kirby * @since <pre>Jun 17, 2011</pre> */ public class Example { private static final String SITE = "http://some.website.com/upload"; private static final int TIME_OUT_SECS = 5; // upload a file and return the response as a string public String post(File file) throws IOException, InterruptedException { final Part[] multiPart = { new FilePart("file", file.getName(), file) }; final EntityEnclosingMethod post = new PostMethod(SITE); post.setRequestEntity(new MultipartRequestEntity(multiPart, post.getParams())); final ExecutorService executor = Executors.newSingleThreadExecutor(); final List<Future<Integer>> futures = executor.invokeAll(Arrays.asList(new KillableHttpClient(post)), TIME_OUT_SECS, TimeUnit.SECONDS); executor.shutdown(); if(futures.get(0).isCancelled()) { throw new IOException(SITE + " has timed out. It has taken more than " + TIME_OUT_SECS + " seconds to respond"); } return post.getResponseBodyAsString(); } private static class KillableHttpClient implements Callable<Integer> { private final EntityEnclosingMethod post; private KillableHttpClient(EntityEnclosingMethod post) { this.post = post; } public Integer call() throws Exception { return new HttpClient().executeMethod(post); } } }
źródło
Wspomniana metoda z najwyższymi wynikami Laza jest przestarzała od wersji 4.3. Dlatego lepiej byłoby użyć obiektu konfiguracji żądania, a następnie zbudować klienta HTTP
private CloseableHttpClient createHttpClient() { CloseableHttpClient httpClient; CommonHelperFunctions helperFunctions = new CommonHelperFunctions(); PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(); cm.setMaxTotal(306); cm.setDefaultMaxPerRoute(108); RequestConfig requestConfig = RequestConfig.custom() .setConnectTimeout(15000) .setSocketTimeout(15000).build(); httpClient = HttpClients.custom() .setConnectionManager(cm) .setDefaultRequestConfig(requestConfig).build(); return httpClient; }
PoolingHttpClientConnectionManager to użytkownik, który ustawia maksymalną domyślną liczbę połączeń i maksymalną liczbę połączeń na trasę. Ustawiłem go odpowiednio na 306 i 108. W większości przypadków wartości domyślne nie będą wystarczające.
Aby ustawić limit czasu: użyłem obiektu RequestConfig. Możesz również ustawić właściwość Limit czasu żądania połączenia, aby ustawić limit czasu oczekiwania na połączenie z Menedżera połączeń.
źródło
Wspomniał o tym już w komentarzu Benvoliota powyżej. Ale myślę, że warto jest post na najwyższym poziomie, ponieważ z pewnością podrapał mnie po głowie. Wysyłam to na wypadek, gdyby to pomogło komuś innemu.
Napisałem prostego klienta testowego i
CoreConnectionPNames.CONNECTION_TIMEOUT
limit czasu działa w tym przypadku idealnie. Żądanie zostanie anulowane, jeśli serwer nie odpowie.W kodzie serwera, który faktycznie próbowałem przetestować, identyczny kod nigdy nie wygasa.
Zmiana go na
CoreConnectionPNames.SO_TIMEOUT
przekroczenie limitu czasu aktywności połączenia gniazda ( ) zamiast połączenia HTTP (CoreConnectionPNames.CONNECTION_TIMEOUT
) rozwiązało problem.Przeczytaj również uważnie dokumentację Apache: http://hc.apache.org/httpcomponents-core-ga/httpcore/apidocs/org/apache/http/params/CoreConnectionPNames.html#CONNECTION_TIMEOUT
Zwróć uwagę na fragment, który mówi
Mam nadzieję, że to uratuje komuś inne drapanie się po głowie, przez które przeszedłem. To nauczy mnie nie czytać dokładnie dokumentacji!
źródło
Op później stwierdził, że używają Apache Commons HttpClient 3.0.1
HttpClient client = new HttpClient(); client.getHttpConnectionManager().getParams().setConnectionTimeout(5000); client.getHttpConnectionManager().getParams().setSoTimeout(5000);
źródło
HttpConnectionParams.setSoTimeout(params, 10*60*1000);// for 10 mins i have set the timeout
Możesz również zdefiniować wymagany czas.
źródło