jeudi 11 février 2010

Bench de framework web service java : Axis2 vs Cxf vs Spring ws

C'est quoi un framework web service? :
Les frameworks web service java ont pour objectif de s'affranchir des problématiques techniques liées à la mise en oeuvre d'un web service pour permettre de se concentrer sur le traitement qui doit être réalisé par celui-ci et de simplifier son appel. Dans les grandes lignes, ils permettent :
  • coté client : de générer les classes à partir d'un WSDL permettant de créer une grappe d'objet correspondant au message SOAP du web service de façon transparente.
  • coté serveur : de récupérer une requête HTTP SOAP, de transformer le contenu du message en une grappe d'objets, d'appeler une méthode java correspondant à la requête puis de récupérer l'objet en retour de l'appel de la méthode et de le transformer en réponse HTTP SOAP.
Plusieurs méthodes de développement sont associées à ces frameworks :
  • Contract first : définir un contrat d'échange et ensuite de s'appuyer sur ce contrat pour développer le service à l'aide du framework.
  • Code first : développer un service java et ensuite s'appuyer sur le framework pour qu'il expose la méthode sous forme de web service.
Ces deux méthodes font débats et je ne vais pas m'attarder dessus dans le cadre de ce bench dont ce n'est pas l'objet. J'y reviendrai peut être dans un autre billet...

Les frameworks testés :
Je me suis attardé sur les frameworks les plus connus :
Objectif du bench:
L'objectif du bench est de mesurer le temps passé dans les couches techniques des frameworks web services en dehors du réel traitement que doit effectuer le web service et cela différent niveau de charge. Le tout est de pouvoir mesurer l'overhead engendré par les frameworks web services par rapport à un appel direct de méthode en java et de comparer cet overhead. Le bench se focalise sur les temps de traitements coté serveur :


Caractéristiques du bench :
  • les web services exposés :
J'ai mis en place le même web service avec les 3 frameworks dans 3 webapps indépendantes. Les temps de réponses sont mesurés coté client. Pour que les temps de réponse coté client correspondent à l'overheard technique coté serveur, le traitement métier est inexistant : Le service java ne fait que renvoyer l'objet récupérer en paramètre :


La requête en entrée ainsi que la réponse en retour sont représentatifs d'un "vrai" web service (dans le sens ou ce n'est pas un simple hello world) : 
    • 60 données unitaires
    • 3 niveaux de profondeur
    • requête SOAP de 3.75 Ko
  • Du coté du client :
J'ai mis en oeuvre un injecteur http maison multithreadé et basé sur commons-httpclient qui envoie directement la requête SOAP prédéfinies et mesure les temps de réponse. J'ai d'abord fait des tests avec SoapUI en local sur mon poste mais je ne voulais pas "pollué" les résultats en saturant le poste client et j'ai donc décidé de mesurer les temps de réponse client à partir d'un serveur plus puissant que mon poste et dédié au bench.
  • Du coté du serveur :
J'ai déployé les 3 webapps dans un JBoss 5.1.0 "out of the box" s'appuyant sur une JVM Sun 1.6.0_18. J'ai simplement augmenté la taille de la JVM.



  • procédure du bench :
J'ai monté en charge les uns après les autres chacun des web services exposés avec : 10, 50 et 100 clients (threads) simultanés effectuant chacun 2000 appels. Le test est répété 4 fois pour vérifier la stabilité des temps  de réponse sur plusieurs essais.

Résultats :




Voici le tableau détaillé : 

Dans le cadre de ce bench, CXF est donc le framework le plus performant suivi d'assez prêt par Spring ws. Axis2 est clairement moins performant indépendamment du niveau de charge coté serveur.

Conclusion :
J'ai été confronté à quelques problèmes de déploiement sur JBoss à cause de librairies utilisées à la fois par les frameworks et par JBoss avec Axis2 et Spring ws. Sur cet aspect là, la communauté et la documentation autour de Spring permettent de résoudre rapidement le problème alors que pour Axis2, il a fallu creuser un peu plus.

13 commentaires:

Thomas Recloux a dit…

Merci Jérèmy pour cet article très detaillé.
Quelle option de marshaling as tu utilisé pour spring-ws ? JAXB ?

Jérémy Sevellec a dit…

@thomas : En effet, j'ai utilisé l'option de marshalling avec Jaxb2 pour obtenir quelque chose de comparable.

Tim a dit…

Pour axis2, tu n'as pas eu de problème de connexion http qui fait un timeout du au fait que le stub client n'est pas threadsafe? De plus, axis2 ne permet par défaut que 2 connexions par requête je crois..

Jérémy Sevellec a dit…

@Tim, mon client est un client basé sur commons-httpclient et non un client axis2.

jpuzzler a dit…

Bonjour,

Je m'occupe récemment du développement du client ws pour ma boite, j'ai obtenu la .wsdl et les .xsd (pour la validation des données). J'ai choisi spring-ws. Peux-tu m'indiquer comment faire pour généré la grappe d'objets en prenant en compte les .xsd avec spring-ws.

Merci

Jérémy Sevellec a dit…

@jupuzzler: Il est en effet possible d'utiliser spring ws coté client (ce n'était pas le cas dans le cadre du bench).La documentation de spring ws sur le sujet est un bon point de départ : http://static.springsource.org/spring-ws/sites/1.5/reference/html/client.html#d0e3378 (chapitre 6.2.2 et chapitre 6.2.3)

Ghalleb a dit…

Très bon article.

Serait-il possible que tu mettes les sources avec?

Jérémy Sevellec a dit…

@Ghalleb : ça aurait été avec plaisir mais le code est lié au client chez lequel j'interviens et je préfère dans ce cadre ne pas le diffuser.

Houssem a dit…

Merci très bien
C'est vraiment très utile.

Anonyme a dit…

Très intéressant, merci!

Simple question: Tu dis t'être attardé sur les principaux frameworks. Est-ce que Sun-Metro n'en fait pas partie, selon toi?

Jérémy Sevellec a dit…

En effet, tu as raison Sun metro en fait aussi partie mais je n'en n'avait que très peu entendu parler. Je ne l'ai pas intégré dans le test car il me paraissait beaucoup moins utilisé mais je me trompe peut être.

Anonyme a dit…

Bonjour,

Super l'article. Il confirme ce que je constate avec le stub Axis 1.5.6.

Pensez-vous qu'il y a moyen de contourner le problème ? Est-ce que la mise en place de MultiThreadedHttpConnectionManager http://axis.apache.org/axis2/java/core/docs/http-transport.html#setting_cached_httpclient_object pourrait régler le souci de montée en charge ?

Merci.

Jérémy Sevellec a dit…

Je pense que le meilleur moyen de contourner le problème c'est de ne pas l'utiliser :-). Plus sérieusement, je ne sais pas, je n'ai pas creuser.