3 votes

Le client CXF JAXRS ne réutilise pas les connexions TCP

J'utilise la prise en charge de JAX-RS dans CXF 2.2.5 pour invoquer des services Web REST. Je crée une seule instance org.apache.cxf.jaxrs.client.WebClient pour chaque point de terminaison avec lequel je dois communiquer (généralement un ou deux points de terminaison pour un déploiement donné) et je réutilise ce client pour chaque invocation de service Web.

Le problème auquel je suis confronté est que le client crée de nouvelles connexions TCP avec le serveur pour chaque demande, malgré l'utilisation du paramètre keep-alive. À des niveaux de trafic élevés, cela pose des problèmes. Un extrait de mon code client est présenté ci-dessous.

J'essaie de fouiller dans les sources CXF pour identifier le problème mais je suis désespérément perdu pour le moment. Toute réflexion est la bienvenue.

Merci, FB

ConcurrentMap<String, WebClient> webclients = new ConcurrentHashMap<String, WebClient>();

public void dispatchRequest(MyRequestClass request, String hostAddress) {

    // Fetch or create the web client if we don't already have one for this hostAddress
    // NOTE: WebClient is only thread-safe if not changing the URI or headers between calls!
    //   http://cxf.apache.org/docs/jax-rs-client-api.html#JAX-RSClientAPI-ThreadSafety
    WebClient client = webclients.get(hostAddress);
    if (client == null) {
        String serviceUrl = APP_HTTP_PROTOCOL + "://" + hostAddress + ":" + APP_PORT + "/" + APP_REQUEST_PATH;
        WebClient newClient = WebClient.create(serviceUrl).accept(MediaType.TEXT_PLAIN);
        client = webclients.putIfAbsent(hostAddress, newClient);
        if (client == null) {
            client = newClient;
        } // Else, another thread must have added the client in the meantime - that's fine if so.
    }

    XStream marshaller = MyCollection.getMarshaller();
    String requestXML = marshaller.toXML(request);

    Response response = null;
    try {
        // Send it!
        response = client.post(requestXML);
    }
    catch (Exception e) {
    }

    ...
}

5voto

agoware Points 66

Dans votre code d'exemple, vous obtenez une réponse JAX-RS, qui getEntity() retournera un InputStream par défaut. Par conséquent, comme CXF n'est pas responsable de la consommation du flux, cette question est évidemment laissée ouverte.

Si vous ne le fermez pas explicitement, il sera fermé pendant une phase de collecte des déchets. Mais même ainsi, en cas de trafic élevé, cette petite latence empêche la connexion HTTP sous-jacente d'être réinsérée dans le pool interne de connexions persistantes exploité par HttpURLConnection (que CXF utilise sous le capot). Elle ne peut donc pas être réutilisée à temps.

Si vous prenez soin de fermer l'InputStream, vous ne devriez plus voir un grand nombre de sockets TIME_WAIT.

1voto

Daniel Kulp Points 8782

J'essaierais certainement de mettre à jour vers une version plus récente et supportée de CXF. Il y a eu BEAUCOUP de mises à jour de JAX-RS dans les nouvelles versions de CXF et ce problème est peut-être déjà résolu.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X