Jazoon, Keynote de Jonas Bonér

Nouvelle journée à Zurich pour Jazoon, nouvelle keynote d’ouverture. Aujourd’hui c’est Jonas Bonér, CTO chez Typesafe qui soulève les problématiques des systèmes scalables, hautement concurrentiels et tolérants à la panne. Cela l’amuse d’ailleurs d’avoir mis autant de buzz-words dans un titre!
On peut tout résumer en un mot : « compromis ». Et ce compromis, il va falloir le trouver dans deux batailles rangées:

  • Performance vs Scalabilité
    Si votre système est rapide avec un utilisateur, lent avec plusieurs, alors vous avez un problème de scalabilité.
    Si votre système est déjà lent avec un utilisateur, alors vous avez des problèmes de performances.
    La scalabilité a un coût, il faut en être conscient.
  • Latence vs Débit
    Il faut trouver le débit maximum pour lequel la latence est acceptable. Qu’est-ce qu’un temps de réponse acceptable? C’est l’affaire de chacun.

Go Concurrent

Il y a encore quelques années, ce n’était pas une problématique majeure. Le sujet devient de plus en plus important depuis cinq ans. Cela vient notamment de l’émergence des processeurs multi-coeurs.
Mais cela ne vient pas sans mal. Et pour Jonas, le mal a un nom : « Les états mutables partagés ». Cela mène a des comportements totalement non-déterministes. Que se cache t’il derrière cette expression? Tout simplement le fait d’avoir des objets mutables qui sont partagés et modifiés par plusieurs threads en même temps. Avec les états partagés, il n’y a qu’une seule solution: les LOCKS. Et c’est cette stratégie qui va écrouler la capacité de scalabilité et le débit de l’application Web.
Il existe des solutions:

  • Dataflow concurrency: déterministe, déclaratif, data-driven mais connait quelques limitations.
  • Actors : rien n’est partagé, tout est isolé, léger, à base d’événements, d’émission et consommation de messages asynchrones. Comme par exemple Akka ou Erlang.
  • Software Transactional Memory : les données en mémoire sont vues comme un dataset dans une base de données, avec les opérations rollback et commit. Le système réessaie automatiquement chaque transaction en cas de collision. On ne peut pas composer les locks entre eux, mais on peut faire chaque transaction en mémoire atomique.

Si vous avez la chance de construire un projet ex nihilo, voici ce qu’il nous conseille:

  • Programmation déterministe, déclarative et imutable (à base de programmation logique et fonctionnelle)
  • Ajout seulement du non-déterminisme si besoin
  • Ajout de la mutabilité si besoin (avec un mécanisme Software Transactional Memory)
  • Ajout des moniteurs, c’est à dire des locks en dernière solution.
    Commencez toujours par le premier point. Si cela ne suffit pas à répondre à votre besoin, passez au second. Le moins de points vous prenez, le plus robuste votre application sera.

Go Fault-tolerant

En java, il est compliqué d’avoir une gestion des erreurs cohérentes à cause d’une chose, les threads. Il n’y a pas un moyen simple de propager les exceptions aux travers des threads. Cela conduit à une programmation défensive et limitante, à base de try{}catch{}finally{try{catch}}…
Ces blocs polluent le code et rendent l’architecture fragile et figée.
La bonne solution serait :

  • Des processus isolés
  • Des processus de supervisions de manière déclarative
  • La sémantique utilisée fonctionne aussi bien en local que distant

Et le pattern Actor/Model, encore lui, résout cela très proprement. Laissez le système tomber, il saura se remettre debout.

Go Faster, Go More

Pour arriver à aller plus vite et plus loin (entendez plus de données), il y a un premier principe à respecter: ne bloquez jamais rien. Utilisez des API NIO (Non blocking I/O) et les serveurs qui supportent ce paradigme. Bloquez des ressources va tout simplement tuer les possibilités de scalabilité de l’application.
Pour ne pas bloquer les ressources, une solution existe : l’asynchronisme. Il vaut mieux pousser de l’information (qui sera traitée plus tard) que de la consommer sur le champ.
Plusieurs techniques nous permettent de faire de l’asynchrone:

  • Actors/Model, et oui encore une fois
  • JMS/AMQP, cela existe toujours. Nous devrions selon lui repenser notre utilisation des middleware de messaging
  • Websockets

Quoi qu’il en soit, il ne faut jamais utiliser une déclaration explicite de thread.

Go distributed

Les systèmes distribués sont la réponse à la demande de performance d’une application qui sert de plus en plus d’utilisateur. Mais la distribution du traitement à un coût, ne serait-ce que le réseau. Le réseau amène en plus sa dose d’incertitude car rien ne peut être garanti à 100% sur le réseau.
Il est très difficile de faire des outils qui ont de bonnes capacités de scalabilité. Son conseil: « il est trop difficile de faire de tels outils. Ne faites pas ça à la maison! Achetez les ou utilisez l’open-source. »

Quelques idées-reçues sur les systèmes distribués:

  • La transparence pour le système: objets distribués, transactions distribuées…tout cela ne fonctionne pas.
  • L’approche RPC bloquant permettant d’invoquer des méthodes de manière synchrone au travers d’un système distribué. Cela ne fonctionne pas non plus.

Au lieu de cela, prenons à bras le corps la complexité, le réseau et vive l’asynchronisme.

Jonas souhaite attirer notre attention sur « The CALM Conjecture » sans plus de détail si ce n’est que la donnée temps n’est plus prise en compte.

Go BIG (Data)

L’approche orienté-objet impérative ne fonctionne pas. Il cite l’API de base d’Hadoop, tout en soulignant que ce n’est pas le moteur qui est terrible, mais l’API de traitement de base. Il faut des processeurs sous formes de fonctions, avec les outils suivants:

  • Object-Mathematics Impedance Mismatch
  • Cascading, Cascalog, Scaling / MapReduce

L’approche par batch ne convient pas non plus. Il faut traiter les données en temps-réel. Il cite alors Spark, Storm, GridGain.

Il se lance ensuite dans les vertus de l’Event Sourcing. On retrouve dans ce billet de Martin Fowler explique très bien ce paradigme.

Conclusion

La présentation est déjà disponible sur un célèbre site de partage. Je l’ai trouvée personnellement très intéressante et très riche. Certes, toutes les applications ne se doivent pas de gérer un milliard d’utilisateurs simultanés. Mais d’auditeurs différents, les mêmes solutions reviennent, l’orienté fonction, le pattern Actor/Model. Il semble qu’il va falloir qu’on s’y fasse car nous n’avons pas fini d’en entendre parler.

Billets sur le même thème :

Laisser un commentaire