Voici un moment que je n’avais pas trouvé le temps d’écrire un nouvel article sur nodecast. Depuis le dernier en juillet 2012, il y a eu énormément d’apprentissage et d’avancées, et même si ce projet n’est pas encore prêt à être utilisé en dehors de mon usage, j’ai bon espoir qu’il puisse être présentable d’ici quelques mois.
Passé
A l’origine j’avais débuté ce projet en tant que backend de mon projet de supervision système nodecast.net. Le frontend web étant en Ruby on Rails il m’a paru évident d’utiliser Ruby pour le backend. Il avait pour but de recevoir les payloads envoyées par mon client natif en Qt/C++ et qui contenaient les informations système (CPU, réseau, mémoire, etc). J’ai utilisé pour ce backend différents serveurs de file d’attente afin de le rendre asynchrone, propriété impérative à tout système ayant la prétention de tenir la charge. Il s’est avéré qu’avec juste quelques clients le backend montait rapidement en charge CPU et mémoire, la faute au langage script et aux innombrables couches de bibliothèques.
Il me fallait donc un langage compilé ce qui me permettait de plus d’éviter des bindings vers mongodb pas forcément optimisé et à jour. Utilisant Qt pour mon client desktop, je me suis lancé dans la réécriture du backend en Qt/C++. Ruby fut malgré tout intéressant car il me permit de développer rapidement un prototype.
La réécriture du backend se fit en plusieurs passes, en fonction des technologies que je testais et des contraintes qui s’imposaient. L’objectif étant d’avoir un minimum de dépendances vers des outils annexes et une stack très légère permettant d’exploiter l’ensemble sur un environnement matériel très léger ou ancien. Pour cela Zeromq supprime la dépendance d’un serveur de file d’attente tout en fournissant les mêmes propriétés, hormis la persistance disque. Je l’ai réglé en stockant les payloads dans mongoDB en sus des autres données.
Coté fonctionnalité, mon backend était typé en fonction du métier de la supervision. J’ai donc travaillé pour sortir le métier du serveur ncs vers des workers externe, cela afin de le rendre générique et facilement adaptable à des besoins différents. Ce travail pris tellement de l’ampleur que j’ai fini par percevoir plus d’intérêt. En effet si un backend générique asynchrone pouvait voir le jour, il permettrait de développer plus rapidement des logiciels, laissant le développeur se concentrer sur son cœur de métier. De plus cela permettrait de séparer l’IHM des traitements, ce qui procure l’immense avantage de développer facilement plusieurs IHM (desktop, mobile, web).
Les payloads envoyées sur l’API HTTP peuvent être du json ou bien des fichiers binaires. Dans ce dernier cas nodecast les stocke dans GridFS pour les transmettre immédiatement aux workers ou lorsqu’un worker en fait la demande. Comme usage on peut très bien imaginer envoyer à nodecast des fichiers vidéos pour les faire traiter à différents workers qui vont les transcoder, les dupliquer, les distribuer, etc. L’upload HTTP ayant ses limites, le service FTP permettra d’envoyer de gros fichiers avec possibilité de resume en cas de coupure.
Présent
A ce jour l’architecture est basée sur Qt, Zeromq et mongoDB. J’étais parti sur le postulat d’offrir des services embarqués dans des threads, ceci pour simplifier l’installation et la configuration. C’était cependant une erreur de sécurité, une simple faille dans un service (FTP par exemple) aurait compromis l’ensemble du processus ncs de nodecast, ensuite cela aurait obligé de futurs contributeurs à utiliser Qt/C++ et à m’assurer de chaque ligne de code de leur service avant de l’intégrer.
Je travaille donc actuellement à externaliser ces services, cependant sans sacrifier en performance puisqu’il resteront en C/C++ ou dans un langage compilé. La difficulté étant de trouver un outil adapté à ces contraintes, j’ai fini par trouver le projet zerogw qui est un serveur HTTP en frontal et un backend vers Zeromq. Dans un simple fichier de configuration, ce serveur permet grâce à des règles de routage de transférer les requêtes HTTP vers le serveur nodecast. Les performances de zerogw sont incomparables avec ce que je pouvais espérer avec la libqxt et cela me permet d’installer ce service sur une machine dédiée, nodecast restant alors au chaud sur un serveur non routable depuis l’extérieur.
Les deux autres services HTTP sont l’IHM web d’administration et le tracker bittorrent. Pour cela j’ai trouvé l’excellent treefrogframework qui propose une stack façon Ruby on Rails en Qt/C++. Cependant puisque les services nodecast seront externes, au même titre que les workers, il sera tout à fait possible de les développer dans un autre langage tel que Go qui possède des frameworks web (Revel, Gorilla) . Quant au service FTP, rien de plus simple de sortir celui que j’ai développé à partir de CftpServer.
L’idée finale étant que ces services communiquent avec nodecast via zeromq voir également via stdin/stdout comme les workers.
Futur
Nodecast, et plus précisément le serveur ncs, se présentera comme un HUB entre des workers et des services. L’utilisateur pourra l’utiliser via l’API HTTP et les différents services, et effectuer ses traitements métiers dans ses workers. L’enchaînement de ses traitements se fait via un workflow qu’il définit lui même. Le workflow est pour l’instant très basique puisque c’est une simple suite ordonnée (worker1 puis worker2, etc). A long terme je souhaite pouvoir conditionner les enchaînements par exemple si le worker1 renvoit true -> worker2a sinon worker2b, puis avec des conditions plus complexes (présence de fichier, date, etc) grâce au state machine framework de Qt.
Enfin le deux derniers services à finaliser seront le serveur XMPP et le tracker bittorrent. Ils permettront la communication et le partage de fichiers entre des utilisateurs depuis une interface native dédiée à cela, cette interface fait partie de mon prochain projet nodeseed.






