Méthode Java préférée pour le ping D'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: Quelle est la meilleure façon de pinguer 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 tout de bon à tous (il va faire ce que je veux)?
  2. dois-je fermer la connexion?
  3. je suppose que c'est une requête GET . Est-il possible d'envoyer HEAD à la place?
138
demandé sur blacktide 2010-08-27 16:43:35

7 réponses

Est-ce tout de bon à tous (il va faire ce que je veux?)

Vous pouvez le faire. Une autre façon possible 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 InetAddress#isReachable() :

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

ceci ne teste cependant pas explicitement le port 80. Vous risquez d'obtenir de faux négatifs en raison d'un blocage du pare-feu d'autres ports.


dois-je fermer la connexion?

Non, vous n'avez pas besoin explicitement. C'est manipulé et regroupé sous les cagoules.


je suppose que c'est une requête GET. Y a-t-il un moyen d'envoyer HEAD à la place?

vous pouvez faites le moulage URLConnection à HttpURLConnection puis utilisez setRequestMethod() pour définir la méthode de requête. Cependant, vous devez tenir compte du fait que certains serveurs webapps pauvres ou maison peut retourner erreur HTTP 405 pour une tête (c.-à-d. pas disponible, Pas mis en œuvre, pas autorisé) alors qu'un GET fonctionne parfaitement bien. L'utilisation de GET est plus fiable dans le cas où vous avez l'intention de vérifier des liens/Ressources pas des domaines/hôtes.


tester la disponibilité du serveur n'est pas suffisant dans mon cas, je dois 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 la webapp n'a pas pu se déployer pendant le démarrage du serveur. Ce sera toutefois généralement pas parce que le serveur entier tombe en panne. 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 d'utilité, en tenant compte également avec des temps morts:

/**
 * 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
répondu 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 aurez lu depuis 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();
        }
    }

aussi vérifier question similaire Comment vérifier si une URL existe ou renvoie 404 avec Java?

Espérons que cette aide.

17
répondu 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 déconnecter.

7
répondu Bill the Lizard 2010-08-27 12:48:15

le code suivant exécute une demande HEAD pour vérifier si le site 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
répondu 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 pouvais-je pas simplement ping ma propre page, ce que je veux à la demande de toute façon? Bien sûr! Vous pouvez même vérifier les deux, si vous voulez la distinction entre "internet" et votre propre les serveurs étant accessible Que si le serveur est en panne? Google DNS (par ex. 8.8.8.8) est le plus grand service public DNS dans le monde. En 2013, elle répond à 130 milliards de demandes par jour. Laissez ‘s juste de dire que votre app répondre ne serait probablement pas le sujet du jour.

lire le lien. son semble très bon

EDIT: dans mon exp de l'utiliser, c'est pas aussi rapide de 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é pour juste vérifier la connexion à internet la première méthode peut devenir lente en raison des variables de connexion.

3
répondu Emad 2017-09-02 06:59:22

envisager d'utiliser le cadre Restlet, qui a une grande sémantique pour ce genre de chose. C'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
répondu 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 de URLConnection qui est utilisée. Je viens de trouver une fuite de ressources dans notre système à cause de ça. Une application a généré beaucoup de connexions suspendues (selon lsof; nous l'exécutons sur JDK1).6) et la raison était que nous avons utilisé exactement le morceau de code que vous avez montré. Les connexions TCP n'ont pas été fermées, par exemple retournées à la piscine, etc. - ils ont été laissés dans un état stabilisé. Dans ce cas précis, le scénario est illustré par YoK - cast (HttpURLConnection) et appeler .déconnecter.)(

0
répondu bartolomeo_n 2013-01-19 12:40:06