Comment gagner au Challenge USI 2011?

Déjà évoqué dans ce précédent billet, le Challenge USI 2011 s’est terminé la semaine dernière lors de l’Université du SI, événement sponsorisé par Octo Technologies.

L’équipe n°10 (Florent Ramière/Jaxio, Nicolas Romanetti/Jaxio, Bernard Pons/Banque de France, Julien Dubois/Ippon Technologies) a terminé 2ème, à un cheveu de l’équipe gagnante (équipe n°6, composée de membres de Xebia). Les technologies utilisées par ces deux équipes sont relativement proches, à la différence près du système de back-end:

  • Gemfire: une solution de cache distribué qui est un produit commercial vendu par la société VMWare, pour l’équipe n°6,
  • Cassandra: une base de données NoSQL distribuée, qui est une solution Open Source de la fondation Apache, pour l’équipe n°10

Nous vous proposons ici de détailler plusieurs des choix qui ont clairement fait la différence.

En effet:

  • Les deux premières équipes ont tenu respectivement 200 000 et 210 000 connections simultanées
  • La 3ème équipe a tenu 40 000 connections
  • Les autres équipes n’ont pas pu dépasser les 12 000 connections

Tout d’abord, la première chose qui a fait la différence n’est pas technique, mais humaine: il est clair que ces deux équipes ont passé énormément de temps sur le challenge, sans doute beaucoup plus que la plupart des autres équipes.

Ensuite, passons à la technique: les deux premières équipes ayant réalisé leur application en Java, en utilisant Netty, on peut en conclure un certain nombre de faits:

  • Java est très bien adapté pour de la haute volumétrie. En l’occurrence, les solutions Java ont ici battu des solutions codées en C, node.js, akka.io… Non seulement le monde a changé (Java tient la charge sur de la haute volumétrie, et peut se battre avec des applications en C), mais les nouvelles solutions à la mode (Node.js et akka.io) ont encore du chemin à faire.
  • Plus spécifiquement, ce sont des solutions Java fortement optimisées qui ont gagné. Par exemple, certains compétiteurs ont utilisé Tomcat. C’est un grand classique de l’informatique: une solution spécialisée est toujours plus performante qu’une solution généraliste. Il ne faut donc pas en conclure que les serveurs d’application Java EE ne sont pas prêts pour ce niveau de charge: ils sont juste moins adaptés qu’un programme spécialisé, d’autant plus que les contraintes du challenge étaient très particulières au niveau HTTP (en particulier le fait de bloquer des requêtes HTTP, ce qui était une simplification de ce que l’on appelle habituellement du “long polling”).
  • Le back-end posant problème, les solutions les plus performantes sont celles qui ont le plus minimisé les accès à ce back-end. Pour les deux solutions gagnantes, les écritures sont toutes asynchrones, afin de ne jamais bloquer de thread utilisée par Netty. D’autre part, les lectures sont réduites grâce à de nombreuses astuces: utilisation d’un hash pour éviter de devoir relire le login/mot de passe de l’utilisateur à chaque requête, le stockage de certaines données du jeu dans un cookie de manière à éviter à avoir à les relire en base… Par contre l’équipe n°6 utilisait un état stocké dans une session HTTP distribuée avec Gemfire, tandis que l’équipe n°10 avait une architecture “stateless” avec des données de session stockées dans un cookie.
  • Une bonne utilisation de l’infrastructure est également primordiale: le tuning de l’OS et de la JVM font une différence énorme. Ubuntu, en standard, ne peut pas supporter ce type de charge, c’est pourquoi sa configuration a du être largement modifiée. Mais il y avait également un avantage à l’équipe qui connaissait bien les faiblesses de l’infrastructure virtualisée fournie: en effet, la configuration VMWare n’allouait que 2 gigas de RAM, pouvant monter à 4 en cas de charge. Il est donc probable que l’équipe n°6, qui a limité sa JVM à 2 Giga, a eu là un avantage: l’utilisation de l’ensemble de la RAM “virtuelle” par l’équipe n°10 ayant probablement fait s’écrouler les machines physiques hôtes. Enfin, l’équipe n°10 a fait l’erreur de sacrifier une machine pour faire des IP virtuelles avec LVS, alors que l’équipe n°6 a mieux géré ses ressources en répartissant cette configuration sur toutes leurs machines: étant donné que le test final n’était que sur 10 machines, cela leur a donc donné un net avantage en termes de puissance de calcul.

Malheureusement la plateforme de test n’a permis que de faire un test avec 10 machines virtuelles en parallèle, et nous ne pouvons donc pas savoir si l’une de ces architectures pouvait effectivement tenir le million d’utilisateurs simultanés, sur 100 machines distribuées, ce qui était l’objectif fiinal du jeu. On voit en effet ici que les contraintes de RAM et de nombre de machines disponibles ont eu un impact important sur les tests réalisés. L’un des effets principaux de la virtualisation a été de cacher aux compétiteurs les CPUs et la RAM rééllement disponibles, ainsi que la configuration réseau exacte, ce qui a eu un effet très négatif sur le tuning, et donc sur les performances finales.

L’équipe n°10 est en train de nettoyer son code avant de le mettre à disposition de tous sur GitHub: nous ne manquerons pas de vous tenir informés sur ce blog et via Twitter.

TwitterFacebookGoogle+LinkedIn
  • lucdew

    Je suis impatient de voir le code et vous remercie d’avance de le publier.
    > Il est donc probable que l’équipe n°6, qui a limité sa JVM à 2 GigaCe n’est pas plutôt sa vm ? D’ ailleurs il serait intéressant de connaitre la taille des JVM et les options.

  • Boillodmanuel

    Il faut préciser que seules les 3 premières équipes ont eu accès aux 10 VMs, les autres équipes ont testé avec 5 VMs seulement.

    Félicitations tout de même aux finalistes.

  • Guillot Nicolas

    Bonsoir,

    Pour ceux qui veulent creuser le sujet le billet suivant est très intéressant:
    http://martinfowler.com/articles/lmax.html

    Peux être donnera-t-il des idées à certains!

    Bonne lecture et bonne soirée!

    Nicolas

  • Alexandre Vasseur

    Ayant pris part au montage de la plateforme VMware (voir par exemple billet ici http://avasseur.blogspot.com/2011/02/vfabric-on-vcloud-meet-vfabric-cloud.html ) je pense qu’il y a quelques points à noter:
    - sur un OS avec une RAM a 4Go, il est clair qu’on ne donne pas 4Go de heap à une JVM, en physique comme en virtuel. L’article semble évoquer cela comme une surprise sans toutefois donner de chiffre précis sur la taille heap max de l’équipe.
    Il n’y avait pas de faiblesse sur l’allocation de la RAM car nous avions configuré un mode réservation sur la RAM pour garantir l’équité des ressources (et non pas d’overcommit mémoire qui peux exister si on le souhaite) et les bench n’ont par ailleurs pas été fait en simultané.
    - le budget matériel nous a contraint en effet à travailler sur des VM à 4Go, alors qu’on peut avoir aujourd’hui des VM allouées avec 1To au besoin avec les solutions VMware
    - je serais intéressé par un commentaire sur le fait d’utiliser du long polling versus du web socket avec node.js+RabbitMQ par exemple – à priori parce que l’injecteur du concours ne savait gérer que du GET/POST http, et du coup à la contrainte que cela à posé sur le choix des technologie de frontaux applicatif. Par exemple il aurait sans doute été possible de mixer websocket sur node.js/RabbitMQ avec Tomcat – proche par exemple de notre appli de démo CloudFoundry http://blog.springsource.com/2011/05/03/using-mongodb-redis-node-js-and-spring-mvc-in-a-single-cloud-foundry-application/
    Quoi qu’il en soit encore bravo pour le niveau d’expertise, d’innovation et d’entrain mis par les équipes dans ce concours!