2011-07-11 3 views
3

J'utilise le support JAX-RS dans CXF 2.2.5 pour appeler les 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 réutilise ce client pour chaque appel de service Web.Le client CXF JAXRS ne réutilise pas les connexions TCP

Le problème auquel je suis confronté est que le client crée de nouvelles connexions TCP au serveur pour chaque requête, malgré l'utilisation du paramètre keep-alive. À des niveaux de trafic élevés, cela cause des problèmes. Un extrait de mon code client est ci-dessous. J'essaye de creuser à travers la source de CXF pour identifier le problème mais être désespérément perdu actuellement. Toutes les pensées ont grandement apprécié.

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) { 
    } 

    ... 
} 

Répondre

4

Dans votre exemple de code que vous obtenez une réponse JAX-RS, qui getEntity() méthode renverra une InputStream par défaut. Par conséquent, étant CXF pas responsable de la consommation du flux, cela est évidemment laissé ouvert.

Si vous ne le fermez pas explicitement, il sera fermé pendant une phase de récupération de place. Mais même ainsi, avec des débits de trafic élevés, cette petite latence empêche la réinsertion de la connexion HTTP sous-jacente dans le pool interne de connexions persistantes exploitées par HttpURLConnection (que CXF utilise sous le capot). Donc, il ne peut pas être réutilisé à temps.

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

+1

Merci agoware, ça a du sens.En attendant, j'ai fini par me dégrader à une approche basique basée sur la connexion Http, Puisque mes demandes étaient simples à formuler et que je n'avais pas vraiment besoin de faire quoi que ce soit avec la réponse, si j'utilise à nouveau CXF, ce sera certainement utile! –

1

Je certainement essayer de mettre à jour une version plus récente et prise en charge de CXF. Il y a eu beaucoup de mises à jour de JAX-RS dans les nouvelles versions de CXF et ce problème peut déjà être corrigé.

+0

J'aimerais, mais je suis coincé avec cette version à l'heure actuelle en raison de certaines dépendances de projet beaucoup plus large en dehors de mon contrôle. :-( –

+0

Dan, j'ai essayé la mise à niveau vers la version 2.4.1 sur ma machine de développement mais j'ai malheureusement rencontré le même problème –

Questions connexes