Post épisode: Mathias découvre Cloudfoundry et le PaaS

Je vous ai donc parlé de mon projet NSynapse (qui commence à dater), et je voulais faire le rapprochement avec un PaaS: CloudFoundry.

Ce qui m’a donné envie d’en parler, c’est l’état d’avancement des solutions PaaS aujourd’hui, mais surtout la présentation de l’architecture interne de CloudFoundry: Presentation:  Cloud Foundry: Design and Architecture
Je vous conseil de la voir avant de lire ce qui suit.

Elle montre à quel point CloudFoundry n’est pas juste un outil de déploiement et de monitoring, mais c’est pour moi un serveur d’application nouvelle génération: multi-techno, avec gestion de scallabilité horizontale, etc.

Ce serveur d’app, j’en ai rêvé pendant des années, et c’est aussi mon projet que je vais dévoiler dans l’épisode finale.

1. Conteneur d’application Web, mais pas que…

L’objectif de ce projet était de fournir un serveur d’application pour l’écosystème .Net, comme il en existe en Java (Tomcat/JBoss/Weblogic/etc.)
Cela explique l’Episode 2: Mathias découvre J2EE

Le but étant de faire quelque chose de cross-plateforme (compatible Mono) afin de ne pas dépendre de IIS et Windows.
Mais je voulais faire plus qu’un serveur Web IIS: je voulais que le serveur d’app contienne des applications de type Web mais aussi de type « Service Windows » ou « Daemon », ou encore de type « Tâche schedulée ».
Cela explique l’Episode 12: Mathias découvre Topshelf

On retrouve cette distinction dans de nombreux PaaS, comme Azure (Web Role et Worker Role).

2. Un mini PaaS

J’avais imaginé une solution qui soit un « bundle » à installer avec le serveur d’app, mais aussi plusieurs middlewares:

  • une base de donnée,
  • une MOM,
  • un cache,
  • etc.

L’inspiration m’est venu de par la succès de EasyPHP qui offre tout ce qu’il faut pour faire une application sans avoir à installer quoi que ce soit d’autre.
Cela explique l’Episode 1: Mathias découvre le PHP
Mais je voulais surtout démocratiser des middlewares comme les Queues ou les Caches en fournissant une implémentation par défaut.

Certains vont me dire que « Windows AppFabric » est la version « PaaS privé » de Windows Azure, et qu’il fournit déjà:

  • la possibilité de faire des applications Web (IIS)
  • la possibilité de faire des tâches schedulées ou des services windows
  • un MOM (MSMQ)
  • un cache distribué (anciennement Velocity maintenant AppFabric Caching)
  • une base SQLServer

Mais tout ça est trop lié à l’OS Windows, et je voulais quelque chose qui s’installe aussi sur les plateformes Linux.

3. Packaging et déploiement multi-instances

Un autre objectif était de pouvoir déployer une application facilement, sur plusieurs serveurs de manière transparente.
Je voulais faire quelque chose qui se rapproche des déploiements de « Processing Unit » avec Gigaspaces: on peut ainsi préciser le nombre d’instances, et le nombre de backup. Gigaspaces s’assure ensuite de déploiement ces instances sur les serveurs disponibles, et en cas de crash de l’un d’entre eux, Gigaspaces re-déploie l’instance qui a crashée sur un autre nœud du cluster.

Ce dernier peut être considéré comme un serveur d’App, car on peut y déployer:

  • des services, appelé Processing Unit, qui effectue des traitements dans le cache ou expose des services
  • des applications Web, des Processing Unit évoluées qui embarque un serveur d’App Jetty

Cela explique l’Episode 5: Mathias découvre Gigaspaces

En parlant de Gigaspaces, ils ne m’ont pas attendu pour faire leur propre PaaS: Cloudify est un PaaS qui exploite les mêmes briques techniques de gestion de cluster (déploiement de multiples instances, monitoring, Self Healing) et le plus beau c’est que c’est gratuit et OpenSource!

Mais quand on dit « multi-instances », ça ne sert à rien s’il n’y a pas un load-balancer au dessus.
Je ne savais pas lequel prendre, et je ne suis pas arrivé à ce stade du développement, ma solution étant mono-serveur pour le moment.

Pour pouvoir déployer, il faut aussi packager. Mieux encore, je voulais gérer une notion de dépendance entre les packages, en m’inspirant d’OSGI:

  • l’application A dépend de B en version 1.0
  • quand je déploie A, ça déploie d’abord B 1.0, le démarre, et passe au déploiement de A

Cela explique l’Episode 3: Mathias découvre Eclipse (et un peu OSGI)
Et l’Episode 4 : Mathias découvre Spring (et un peu plus OSGI)

Il m’a fallut alors inventer une API commune aux application (pour gérer le cycle de vie start/stop/restart) et un format de package (c’était avant qu’OpenWrap et Nuget existent).
J’avais étudié des solutions de « plugin », mais rien ne me satisfaisait.
En fait, ça se rapproche plus des notions de « Recipes/Cookbooks » qu’il y a dans les solutions comme Puppet, Chef ou Cloudify.

4. Binding de service transparent

Je ne voulais pas que cette notion de dépendance s’arrête aux applications .Net, je voulais l’étendre aux middlewares:

  • l’application A dépend de MySQL et de QPid

La notion de dépendance entre application .Net fonctionne, mais pas celle avec les middlewares.

Je voulais d’ailleurs m’abstraire de l’implémentation et avoir des dépendances de « services »:

  • l’application A dépend d’un service SQL et Amqp: les implémentations seront fournies par MySQL et QPid
  • l’application A dépend du WebService « Pricing »: l’implémentation sera fournie par l’application B

Cela explique l’Episode 7: Mathias découvre Unity+WPF+MVVM
Et aussi l’Episode 9: Mathias découvre MEF

J’ai bloqué sur le sujet car je ne voyais pas comment marier la notion de dépendance vers des services avec la notion de dépendance d’application.
En fait, pour abstraire la notion de service, il me fallait faire une « annuaire de services » ou une découverte de service dynamique.
C’est pour cela que j’ai étudié DBus Sharp et le protocole Zeroconf et aussi COM.
Cela explique « DBus avec .Net » et l’Episode 8: Mathias découvre COM

Je voulais aussi abstraire la communication entre les service avec un « Service Bus » maison: l’objectif étant d’avoir une middleware entre les applications qui assure la communication, et ainsi les applications n’ont pas un lien « en dure » entre elles (ne connaissent pas l’IP de leurs dépendances).
DCOM et DBus font exactement cela, mais je voulais quelque chose d’asynchrone avec une couche de « Messaging » comme « NServiceBus » ou « MassTransite« .
Je voulais faire un service bus maison car je voulais quelque chose de plus light que ce qui existe, je me suis alors lancé en utilisant ZeroMQ et le format Protobuf.
Vu l’ampleur du travail j’ai abandonné :)

5. En conclusion:

Si vous avez été suffisamment courageux pour lire tout ce qui précède, et que vous avez pris le temps de voir la présentation de l’architecture de CloudFoundry, vous allez voir qu’il y a de grosses similitudes:

  • Cloudfoundry possède un « conteneur d’application générique » qui peut être du Java, PHP etc. et pas seulement une application Web
  • Cloudfoundry fournie de base des services, comme MySQL, mais avec des services modernes, comme MongoDB et RabbitMQ
  • Cloudfoundry abstrait la notion de déploiement multi-site et d’instances, et vient avec un LoadBalancer  grâce à son Routeur
  • Cloudfoundry n’offre pas de dépendance entre applications, mais le fait entre les applications et les services, à l’aide du « bind de service »
  • Cloudfoundry utilise son propre format de packaging pour le déploiement (voir: http://blog.cloudfoundry.com/2011/04/18/what-happens-when-you-vmc-push-an-application-to-cloud-foundry/ )
  • Cloudfoundry se repose sur une couche de messaging pour faire communiquer les différentes briques dans une environnement distribué

Je me dis alors que c’est la démarche à suivre, la bonne architecture.
Cloudfoundry ne fait pas encore tout ce que j’avais prévu, et plus aussi.
Est-ce que ça vaut toujours le coup de faire son propre « Cloudfoundry like », un PaaS simple et spécifique .Net ?
Étant donnée que Cloudfoundry peut aussi contenir des applications .Net, est-ce qu’il ne vaut pas mieux parier dessus?

La question reste ouverte, mais ce projet m’aura appris pas mal de chose entre temps…

Suivre

Recevez les nouvelles publications par mail.