Méthode Java préférée pour envoyer un ping à une URL HTTP pour la disponibilité


J'ai besoin d'une classe monitor qui vérifie régulièrement si une URL HTTP donnée est disponible. Je peux m'occuper de la partie" régulièrement " en utilisant l'abstraction Spring TaskExecutor, donc ce n'est pas le sujet ici. La question est: Quel est le moyen préféré de ping une URL en java?

Voici mon code actuel comme point de départ:

try {
    final URLConnection connection = new URL(url).openConnection();
    connection.connect();
    LOG.info("Service " + url + " available, yeah!");
    available = true;
} catch (final MalformedURLException e) {
    throw new IllegalStateException("Bad URL: " + url, e);
} catch (final IOException e) {
    LOG.info("Service " + url + " unavailable, oh no!", e);
    available = false;
}
  1. Est - ce bon du tout (fera-t-il ce que je veux)?
  2. Dois-je en quelque sorte fermer la connexion?
  3. je suppose que c'est une demande GET. Existe-t-il un moyen d'envoyer HEAD à la place?
Author: blacktide, 2010-08-27

7 answers

Est - ce bon du tout (fera-t-il ce que je veux?)

Vous pouvez le faire. Un autre moyen est d'utiliser java.net.Socket.

public static boolean pingHost(String host, int port, int timeout) {
    try (Socket socket = new Socket()) {
        socket.connect(new InetSocketAddress(host, port), timeout);
        return true;
    } catch (IOException e) {
        return false; // Either timeout or unreachable or failed DNS lookup.
    }
}

Il y a aussi le InetAddress#isReachable():

boolean reachable = InetAddress.getByName(hostname).isReachable();

Cependant, cela ne teste pas explicitement le port 80. Vous risquez d'obtenir de faux négatifs en raison d'un pare-feu bloquant d'autres ports.


Dois-je en quelque sorte fermer la connexion?

Non, vous n'avez pas explicitement besoin. C'est manipulé et mis en commun sous les hottes.


Je suppose que c'est une demande GET. Y a-t-il un moyen d'envoyer la TÊTE à la place?

, Vous pouvez lancer le obtenu URLConnection pour HttpURLConnection et ensuite utiliser setRequestMethod() pour définir la méthode de la requête. Cependant, vous devez tenir compte du fait que certaines applications Web ou serveurs locaux médiocres peuvent renvoyer Erreur HTTP 405 pour une TÊTE (c'est-à-dire non disponible, non implémenté, non autorisé) alors qu'un GET fonctionne parfaitement bien. L'utilisation de GET est plus fiable au cas où vous auriez l'intention de vérifier les liens/ressources et non les domaines/hôtes.


Tester la disponibilité du serveur ne suffit pas dans mon cas, j'ai besoin de tester l'URL (la webapp peut ne pas être déployée)

En Effet, la connexion d'un hôte informe seulement si l'hôte est disponible, pas si le contenu est disponible. Il peut aussi bien arriver qu'un serveur Web ait démarré sans problème, mais que l'application Web n'ait pas pu se déployer lors du démarrage du serveur. Ce ne causera cependant généralement pas la panne de l'ensemble du serveur. Vous pouvez le déterminer en vérifiant si le code de réponse HTTP est 200.

HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestMethod("HEAD");
int responseCode = connection.getResponseCode();
if (responseCode != 200) {
    // Not OK.
}

// < 100 is undetermined.
// 1nn is informal (shouldn't happen on a GET/HEAD)
// 2nn is success
// 3nn is redirect
// 4nn is client error
// 5nn is server error

Pour plus de détails sur les codes d'état de réponse, voir RFC 2616 section 10. Appeler connect() n'est d'ailleurs pas nécessaire si vous déterminez les données de réponse. Il se connectera implicitement.

Pour référence future, voici un exemple complet dans la saveur d'une méthode utilitaire, en tenant également compte des délais d'attente:

/**
 * Pings a HTTP URL. This effectively sends a HEAD request and returns <code>true</code> if the response code is in 
 * the 200-399 range.
 * @param url The HTTP URL to be pinged.
 * @param timeout The timeout in millis for both the connection timeout and the response read timeout. Note that
 * the total timeout is effectively two times the given timeout.
 * @return <code>true</code> if the given HTTP URL has returned response code 200-399 on a HEAD request within the
 * given timeout, otherwise <code>false</code>.
 */
public static boolean pingURL(String url, int timeout) {
    url = url.replaceFirst("^https", "http"); // Otherwise an exception may be thrown on invalid SSL certificates.

    try {
        HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
        connection.setConnectTimeout(timeout);
        connection.setReadTimeout(timeout);
        connection.setRequestMethod("HEAD");
        int responseCode = connection.getResponseCode();
        return (200 <= responseCode && responseCode <= 399);
    } catch (IOException exception) {
        return false;
    }
}
 237
Author: BalusC, 2016-02-26 09:41:25

Au lieu d'utiliser URLConnection, utilisez HttpURLConnection en appelant openConnection() sur votre objet URL.

Puis utilisez getResponseCode () vous donnera la réponse HTTP une fois que vous avez lu à partir de la connexion.

Voici le code:

    HttpURLConnection connection = null;
    try {
        URL u = new URL("http://www.google.com/");
        connection = (HttpURLConnection) u.openConnection();
        connection.setRequestMethod("HEAD");
        int code = connection.getResponseCode();
        System.out.println("" + code);
        // You can determine on HTTP return code received. 200 is success.
    } catch (MalformedURLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } finally {
        if (connection != null) {
            connection.disconnect();
        }
    }

Vérifiez également la question similaire Comment vérifier si une URL existe ou renvoie 404 avec Java?

J'espère que cela aide.

 17
Author: YoK, 2017-05-23 12:34:38

Vous pouvez également utiliser HttpURLConnection, ce qui vous permet de définir la méthode de requête (à HEAD par exemple). Voici un exemple qui montre comment envoyer une demande, lire la réponse et se déconnecter.

 7
Author: Bill the Lizard, 2010-08-27 12:48:15

Le code suivant effectue une demande HEAD pour vérifier si le site Web est disponible ou non.

public static boolean isReachable(String targetUrl) throws IOException
{
    HttpURLConnection httpUrlConnection = (HttpURLConnection) new URL(
            targetUrl).openConnection();
    httpUrlConnection.setRequestMethod("HEAD");

    try
    {
        int responseCode = httpUrlConnection.getResponseCode();

        return responseCode == HttpURLConnection.HTTP_OK;
    } catch (UnknownHostException noInternetConnection)
    {
        return false;
    }
}
 4
Author: BullyWiiPlaza, 2015-04-04 15:01:31

Ici l'écrivain suggère ceci:

public boolean isOnline() {
    Runtime runtime = Runtime.getRuntime();
    try {
        Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");
        int     exitValue = ipProcess.waitFor();
        return (exitValue == 0);
    } catch (IOException | InterruptedException e) { e.printStackTrace(); }
    return false;
}

Questions possibles

  • Est-ce vraiment assez rapide?Oui, très rapide!
  • Ne pourrais-je pas simplement envoyer un ping à ma propre page, ce que je veux pour demander de toute façon? Ben voyons! Vous pouvez même vérifier les deux, si vous voulez faire la différence entre "connexion Internet disponible" et la vôtre serveurs accessibles Que se passe - t-il si le DNS est en panne? Google DNS (par exemple 8.8.8.8) est le plus grand service DNS public au monde. En 2013 il sert 130 milliards de dollars demande un jour. Disons simplement, votre application pas répondre ne serait probablement pas le discours du jour.

Lire le lien. cela semble très bon

MODIFIER: dans mon exp de l'utiliser, ce n'est pas aussi rapide que cette méthode:

public boolean isOnline() {
    NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo();
    return netInfo != null && netInfo.isConnectedOrConnecting();
}

Ils sont un peu différents mais dans la fonctionnalité de vérification de la connexion à Internet, la première méthode peut devenir lente en raison des variables de connexion.

 3
Author: Emad, 2017-09-02 06:59:22

Envisagez d'utiliser le framework Restlet, qui a une grande sémantique pour ce genre de chose. Il est puissant et flexible.

Le code pourrait être aussi simple que:

Client client = new Client(Protocol.HTTP);
Response response = client.get(url);
if (response.getStatus().isError()) {
    // uh oh!
}
 2
Author: Avi Flax, 2010-08-27 13:36:55

Wrt 2.: vous feriez mieux de la fermer. Cependant, cela peut dépendre de l'implémentation particulière d'URLConnection qui est utilisée. Je viens de finir de traquer une fuite de ressources dans notre système juste à cause de cela. Une application a généré beaucoup de connexions suspendues (selon lsof; nous l'exécutons sur JDK1.6) et la raison en est que nous avons utilisé exactement le morceau de code que vous avez montré. Les connexions TCP n'ont pas été fermées ni renvoyées au pool, etc. - ils ont été laissés dans ESTABILISHED état. Dans ce cas, le scénario approprié est celui affiché par YoK-cast it (HttpURLConnection) et invoke .déconnecter().

 0
Author: bartolomeo_n, 2013-01-19 12:40:06