HttpClient Timeout

HttpClient-Timeout

1. Überblick

Dieses Tutorial zeigt, wie manconfigure a timeout with the Apache HttpClient 4 macht.

Wenn Sie tiefer graben und andere coole Dinge lernen möchten, die Sie mit dem HttpClient tun können, gehen Sie zuthe main HttpClient tutorial.

Weitere Lektüre:

HTTP-Client-Verbindungsverwaltung

So öffnen, verwalten und schließen Sie Verbindungen mit dem Apache HttpClient 4.

Read more

HttpClient 4 - Folgen Sie den Umleitungen für den POST

So aktivieren Sie die POST-Umleitung mit Apache HttpClient.

Read more

Erweiterte HttpClient-Konfiguration

HTTP-Client-Konfigurationen für erweiterte Anwendungsfälle.

Read more

2. Konfigurieren Sie Zeitüberschreitungen über die Parameter von RawString

HttpClient enthält viele Konfigurationsparameter, die alle generisch und kartenartig eingestellt werden können.

Es gibt3 timeout parameters to configure:

DefaultHttpClient httpClient = new DefaultHttpClient();

int timeout = 5; // seconds
HttpParams httpParams = httpClient.getParams();
httpParams.setParameter(
  CoreConnectionPNames.CONNECTION_TIMEOUT, timeout * 1000);
httpParams.setParameter(
  CoreConnectionPNames.SO_TIMEOUT, timeout * 1000);
httpParams.setParameter(
  ClientPNames.CONN_MANAGER_TIMEOUT, new Long(timeout * 1000));

3. Konfigurieren Sie Timeouts über die API

Der wichtigere dieser Parameter - nämlich die ersten beiden - kann auch über eine typsichere API eingestellt werden:

DefaultHttpClient httpClient = new DefaultHttpClient();

int timeout = 5; // seconds
HttpParams httpParams = httpClient.getParams();
HttpConnectionParams.setConnectionTimeout(
  httpParams, timeout * 1000); // http.connection.timeout
HttpConnectionParams.setSoTimeout(
  httpParams, timeout * 1000); // http.socket.timeout

Der dritte Parameter hat keinen benutzerdefinierten Setter inHttpConnectionParams und muss weiterhin manuell über die MethodesetParameter eingestellt werden.

4. Konfigurieren Sie Timeouts mit dem neuen 4.3. Baumeister

Die in 4.3 eingeführte fließende Builder-API liefertthe right way to set timeouts at a high level:

int timeout = 5;
RequestConfig config = RequestConfig.custom()
  .setConnectTimeout(timeout * 1000)
  .setConnectionRequestTimeout(timeout * 1000)
  .setSocketTimeout(timeout * 1000).build();
CloseableHttpClient client =
  HttpClientBuilder.create().setDefaultRequestConfig(config).build();

Dies ist die empfohlene Methode, um alle drei Zeitüberschreitungen typsicher und lesbar zu konfigurieren.

5. Timeout-Eigenschaften erklärt

Lassen Sie uns nun erklären, was diese verschiedenen Arten von Zeitüberschreitungen bedeuten:

  • Connection Timeout (http.connection.timeout) - die Zeit zum Herstellen der Verbindung mit dem Remote-Host

  • Socket Timeout (http.socket.timeout) - die Wartezeit auf Daten - nach dem Herstellen der Verbindung; maximale Zeit der Inaktivität zwischen zwei Datenpaketen

  • Connection Manager Timeout (http.connection-manager.timeout) - Die Zeit, um auf eine Verbindung vom Verbindungsmanager / Pool zu warten

Die ersten beiden Parameter - das Verbindungs-Timeout und das Socket-Timeout - sind die wichtigsten. Das Festlegen eines Zeitlimits für das Herstellen einer Verbindung ist jedoch in Szenarien mit hoher Last auf jeden Fall wichtig. Aus diesem Grund sollte der dritte Parameter nicht ignoriert werden.

6. Verwenden SieHttpClient

Nach der Konfiguration können wir nun den Client verwenden, um HTTP-Anforderungen auszuführen:

HttpGet getMethod = new HttpGet("http://host:8080/path");
HttpResponse response = httpClient.execute(getMethod);
System.out.println(
  "HTTP Status of response: " + response.getStatusLine().getStatusCode());

Mit dem zuvor definierten Clientthe connection to the host will time out in 5 seconds. Wenn die Verbindung hergestellt wird, aber keine Daten empfangen werden, beträgt das Zeitlimit ebenfalls5 additional seconds.

Beachten Sie, dass das Verbindungszeitlimit dazu führt, dass einorg.apache.http.conn.ConnectTimeoutException ausgelöst wird, während das Socket-Zeitlimit zu einemjava.net.SocketTimeoutException führt.

7. Harte Auszeit

Während das Festlegen von Zeitüberschreitungen beim Herstellen der HTTP-Verbindung und beim Nichtempfangen von Daten sehr nützlich ist, müssen wir manchmalhard timeout for the entire request festlegen.

Zum Beispiel passt der Download einer möglicherweise großen Datei in diese Kategorie. In diesem Fall wird die Verbindung möglicherweise erfolgreich hergestellt, Daten werden möglicherweise konsistent übertragen, wir müssen jedoch weiterhin sicherstellen, dass der Vorgang einen bestimmten Zeitschwellenwert nicht überschreitet.

HttpClient hat keine Konfiguration, mit der wir ein Gesamtzeitlimit für eine Anforderung festlegen können. Es liefert jedochabort functionality for requests, sodass wir diesen Mechanismus nutzen können, um einen einfachen Timeout-Mechanismus zu implementieren:

HttpGet getMethod = new HttpGet(
  "http://localhost:8080/httpclient-simple/api/bars/1");

int hardTimeout = 5; // seconds
TimerTask task = new TimerTask() {
    @Override
    public void run() {
        if (getMethod != null) {
            getMethod.abort();
        }
    }
};
new Timer(true).schedule(task, hardTimeout * 1000);

HttpResponse response = httpClient.execute(getMethod);
System.out.println(
  "HTTP Status of response: " + response.getStatusLine().getStatusCode());

Wir verwendenjava.util.Timer undjava.util.TimerTask, um nach einem harten Timeout von 5 Sekunden einsimple delayed task which aborts the HTTP GET request einzurichten.

8. Timeout und DNS Round Robin - etwas, das Sie beachten sollten

Es ist durchaus üblich, dass einige größere Domänen eine DNS-Round-Robin-Konfiguration verwenden - im Wesentlichen mitthe same domain mapped to multiple IP addresses. Dies bringt eine neue Herausforderung für eine Zeitüberschreitung bei einer solchen Domain mit sich, einfach weil HttpClient versucht, eine Verbindung zu dieser Domain herzustellen, bei der das Zeitlimit abläuft:

  • HttpClient erhältthe list of IP routes in diese Domäne

  • es versuchtthe first one - das Zeitlimit (mit den von uns konfigurierten Zeitüberschreitungen)

  • es versuchtthe second one - das läuft auch ab

  • und so weiter …

Also, wie Sie sehen können -the overall operation will not time out when we expect it to. Stattdessen tritt eine Zeitüberschreitung auf, wenn alle möglichen Routen abgelaufen sind. Darüber hinaus geschieht dies für den Client vollständig transparent (es sei denn, Sie haben Ihr Protokoll auf DEBUG-Ebene konfiguriert).

Hier ist ein einfaches Beispiel, mit dem Sie dieses Problem ausführen und replizieren können:

int timeout = 3;
RequestConfig config = RequestConfig.custom().
  setConnectTimeout(timeout * 1000).
  setConnectionRequestTimeout(timeout * 1000).
  setSocketTimeout(timeout * 1000).build();
CloseableHttpClient client = HttpClientBuilder.create()
  .setDefaultRequestConfig(config).build();

HttpGet request = new HttpGet("http://www.google.com:81");
response = client.execute(request);

Sie werden die Wiederholungslogik mit einer DEBUG-Protokollstufe bemerken:

DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.google.com/173.194.34.212:81
DEBUG o.a.h.i.c.HttpClientConnectionOperator -
 Connect to www.google.com/173.194.34.212:81 timed out. Connection will be retried using another IP address

DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.google.com/173.194.34.208:81
DEBUG o.a.h.i.c.HttpClientConnectionOperator -
 Connect to www.google.com/173.194.34.208:81 timed out. Connection will be retried using another IP address

DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.google.com/173.194.34.209:81
DEBUG o.a.h.i.c.HttpClientConnectionOperator -
 Connect to www.google.com/173.194.34.209:81 timed out. Connection will be retried using another IP address
//...

9. Fazit

In diesem Tutorial wurde erläutert, wie Sie die verschiedenen Arten von Zeitüberschreitungen konfigurieren, die fürHttpClient verfügbar sind. Es wurde auch ein einfacher Mechanismus für ein hartes Timeout einer laufenden HTTP-Verbindung veranschaulicht.

Die Implementierung dieser Beispiele kann inthe GitHub project gefunden werden.