Spring User Group : applications concurrentes et distribuées
Dave Syer nous a fait le plaisir de venir pour une présentation au Spring User Group le jeudi 9 décembre. Dave est le leader du projet Spring Batch et est commiteur sur plusieurs projets open source comme Spring Integration, Spring AMQP ou encore le moteur BPM Activiti. Sa présentation portait sur le développement d’applications concurrentes et distribuées, sujet pointu mais qui a attiré suffisamment de monde pour remplir toute la salle. Nous vous proposons ici un résumé des principaux points que Dave a abordés.
Pourquoi sommes-nous là ?
Non, je ne vais pas vous parler du sens de la vie, mais plutôt des objectifs de la présentation. Il s’agit d’expliquer ce qu’est une application concurrente et distribuée, et aussi de mettre en évidence les pièges courants lors de l’implémentation. Spring User Group oblige, Dave expliquera de quelle manière Spring peut aider dans l’implémentation.
Pourquoi une application concurrente ?
Rendre une application concurrente n’est pas une fin en soi, on rend une application concurrente pour qu’elle monte mieux en charge, qu’elle ait de meilleurs performances. Cela passe notamment par une meilleure exploitation du matériel.
Que faire avec plusieurs coeurs ?
Les serveurs multi-coeurs et multi-processeurs sont monnaie courante maintenant. Dave rappelle qu’il est important d’exploiter toute cette puissance de calcul au mieux. Bref, ne pas savoir utiliser ce matériel revient à gaspiller son argent. Une première utilisation consiste à faire tourner plusieurs programmes sur une même machine, chaque programme exploitant un coeur ou un processeur. C’est le principe de la virtualisation et Dave nous rappelle que c’est exactement ce que fait VMWare.
Une deuxième utilisation de matériel multi-coeurs/processeurs est d’avoir une application qui est capable d’exploiter correctement ce potentiel. Cela passe évidemment par le système d’exploitation mais aussi par l’application elle-même. En Java, il s’agit d’utiliser correctement les threads, notamment avec les API concurrentes disponibles depuis Java 5. Spring propose des utilitaires intéressants, comme l’abstraction TaskExecutor
, un support pour le scheduling, la possibilité d’effectuer des appels asynchrones de façon transparente avec l’annotation @Async
.
Dave fait ensuite une démo basée sur un exemple de bar qui reçoit des commandes et doit préparer les boissons correspondantes le plus vite possible. Un goulet d’étranglement est rapidement mis en évidence : la préparation des boissons chaudes. Dave le corrige en multi-threadant la préparation. La démo est basée sur Spring Integration et montre comment on peut facilement rectifier le tir sans impact sur le code applicatif. Une modélisation adaptée – basée sur du messaging – et le framework ont permis de scaler plus facilement.
C’est dangereux le multi-threading ?
Dave rappelle aussi qu’on ne peut pas paralléliser n’importe comment. Le code accédé par plusieurs threads doit être thread-safe. Il existe plusieurs techniques pour être thread-safe : ne pas avoir d’état (stateless), avoir un état mais ne pas le changer (immuabilité), avoir un état mais ne pas le partager, synchroniser avec tout ce qui est disponible en Java (synchronized, Lock
, Semaphone
et consorts), confiner l’état dans chaque thread (ThreadLocal
).
Dans le même registre que le confinement avec une variable ThreadLocal
, Spring peut aider aider à rendre du code thread-safe grâce à la notion de scope. C’est ce que fait Spring Batch avec le scope step
, qui permet d’avoir une instance dédiée pour un step donné.
Un petit peu de messaging
Une architecture orientée message permet le découplage entre les émetteurs et les consommateurs de messages. Le messaging est utile pour les systèmes distribués afin d’intégrer des applications ensemble. On peut aussi l’utiliser pour avoir de meilleures performances, comme dans l’exemple du bar avec Spring Integration. Avec le messaging, on est donc à cheval entre les notions de concurrence et de distribution.
SEDA
Dave introduit la notion de SEDA, pour staged event-driven architecture. L’idée d’une SEDA est de décomposer un traitement en une suite d’opérations. Chaque opération est elle-même composée d’un ensemble de messages à traiter, qui sont dispatchés à un ou plusieurs workers. L’avantage d’une telle architecture est de pouvoir laisser un framework s’occuper de l’enchaînement des étapes et du dispatching. On revient à la même idée que le bar avec Spring Integration : on peut se concentrer sur le code applicatif et laisser au framework la partie technique. L’amélioration des performances peut passer par un simple changement de configuration. Un changement de configuration permet de jouer sur le framework pour avoir les performances que l’on souhaite.
Des ESBs comme ServiceMix permettent d’utiliser des SEDAs.
Application ou système distribués ?
Dave fait la distinction entre application et système distribués. Une application distribuée utilise les mêmes binaires sur plusieurs noeuds. L’exemple classique est le clustering, où l’on distribue l’application pour des contraintes de performances. Les problématiques seront alors la réplication des sessions HTTP ou d’un cache. Un système distribué est fait d’applications distribuées sur plusieurs noeuds. Les binaires ne sont plus les mêmes, les cycles de release entre applications sont différents, on est davantage dans une problématique d’intégration. C’est là que des solutions de messaging prennent du sens, grâce au découplage qu’elles apportent.
D’autres sujets abordés pour les applications distribuées : RPC vs messaging pour faire communiquer des applications entre elles, gestion des transactions distribuées (quand une transaction s’étale sur plusieurs ressources, comme une base de données et une queue JMS) avec ou sans JTA, GemFire comme solution de cache distribué et son support pour Spring.
Conclusion
Dave nous a livré un condensé d’informations sur les applications concurrentes et distribuées. Il était intéressant de voir comment un design et des outils adaptés permettent d’améliorer le comportement d’une application. Si vous souhaitez en apprendre plus :