Greboca  

Suport technique et veille technologique

Aujourd’hui, les grandes entreprises et administrations publiques hésitent entre continuer à utiliser des logiciels propriétaires ou basculer vers les Logiciels Libres. Pourtant, la plupart des logiciels libres sont capables de bien traiter les données issues des logiciels propriétaire, et parfois avec une meilleur compatibilité.

C’est alors la barrière de la prise en main qui fait peur, et pourtant...

Les logiciels libres

L’aspect « Logiciel Libre » permet une évolution rapide et une plus grande participation des utilisateurs. Les aides et tutoriels foisonnent sur Internet ou sont directement inclus dans le logiciel lui-même.

Enfin, les concepteurs sont plus proches des utilisateurs, ce qui rend les logiciels libres plus agréable à utiliser et conviviaux.

Grâce à la disponibilité des logiciels libres, vous trouverez facilement des services de support techniques et la licence n’est plus un frein à l’utilisation de ces logiciels par votre personnel.

Notre support technique concerne essentiellement les logiciels libres, que ce soit sous forme de services ponctuels ou de tutoriels.

DLFP - Dépêches  -  Movim, mode d’emploi — Première partie : l’architecture

 -  Août 2018 - 

Je travaille maintenant depuis presque dix ans sur Movim et je n’ai jamais réellement eu l’opportunité d’expliquer comment le projet fonctionne. Prenons un peu le temps de mettre tout ça par écrit !

Cette présentation sera divisée en plusieurs articles. Je vais commencer par présenter le projet de façon globale avant d’aller progressivement vers son fonctionnement interne et ses détails techniques.

Sommaire

J’utilise les plates‐formes sociales depuis pas mal d’années maintenant et je suis toujours surpris de voir que malgré les milliards de dollars investis par les géants du Web elles fonctionnent toutes plus ou moins selon la même architecture.

Même avec toutes les technologies qui sont apparues ces dernières années les choses se présentent toujours plus ou moins de la même façon : vous publiez du contenu via des requêtes AJAX (ou au travers d’un Websocket), c’est sauvegardé dans une base de données et vos contacts vont périodiquement envoyer une requête au serveur pour voir si il y a quelque chose de nouveau à afficher.

C’est au final assez facile à construire et si vous souhaitez le faire vous‐même il existe de nombreux cadriciels qui offrent tous les outils nécessaires pour réaliser cette architecture aisément (typiquement Laravel, Ruby on Rails, Django, Symfony ou Zend, connectés à une base de données SQL, une API REST, une jolie interface et hop vous avez un réseau social).

Mais pourquoi donc devoir attendre pour récupérer les publications des autres contacts ?

Nous avons depuis des décennies maintenant des technologies de messagerie instantanée qui nous permettent d’envoyer, en temps réel, tout autour du globe, du contenu sans le moindre souci. Pourquoi ne pouvons‐nous pas faire de même avec les réseaux sociaux ?

Et c’est ici que réside l’idée de base du projet Movim.

Créons un réseau social temps réel

Donc, l’une des erreurs à éviter quand le projet a démarré, c’était de réinventer la roue. Vous verrez que Movim est principalement composé de technologies basiques et déjà éprouvées.

Pour fabriquer un réseau social fonctionnant en temps réel, il me fallait transférer du contenu instantanément sur le réseau. Il devait donc être transporté au sein d’un système « connecté » et donc construit sur des sockets (contrairement aux systèmes construits sur des requêtes).

Cela exclut déjà toutes les récentes technologies sociales standardisées par le W3C (bye bye ActivityPub et WebSub), ces dernières étant construites sur HTTP. Loin de moi l’idée de remettre en question ces standards, ce sont des solutions sérieuses et parfaitement valides, mais pas pour les besoins de Movim.

Je cherchais donc un protocole qui soit :

  • temps réel ;
  • standard (avec des RFC sérieuses) ;
  • et si possible déjà éprouvé et largement déployé.

Cela nous amène donc à XMPP (je ne vais pas expliquer en détail comment le protocole est construit, vous pouvez trouver plus d’informations sur la page Wikipedia et sur le site officiel de la fondation).

Logo de XMPP

Dans la pratique, XMPP nous offre quelques précieux avantages :

  • c’est un protocole temps réel (super !), les données sont échangées dans le format XML (oui, je vous vois déjà venir, vous les défenseurs du JSON ! Mais gardons de côté ce différend pour plus tard ;)) sous forme de paquets (appelés « stanzas » dans le cas présent) envoyés en TCP et chiffrés avec TLS ;
  • XMPP offre un cadriciel très simple et générique qui comprend de (très !) nombreuses extensions que l’on peut combiner afin de développer la solution désirée (voici pour l’exemple celles utilisées pour construire Movim) ; et parce que XMPP est basé sur XML, il est très facile de l’étendre au moyen d’espaces de noms (namespaces) existants : prenez Atom, ajoutez‐y Pubsub et voilà, vous obtenez un système de publication de contenu complet, temps réel, pour vos articles avec pièces jointes, bien défini et tout à fait spécifié ;
  • vous pouvez faire bien plus que de simples choses « sociales » avec XMPP ; pas besoin de composer avec dix autres protocoles, XMPP offre déjà tout pour faire du clavardage et des salons de discussion, de la vidéoconférence, des solutions de publication-abonnement et beaucoup d’autres choses. Et cela offre l’avantage de conserver un code assez concis puisqu’il n’y a qu’un unique protocole dans le back‐end ;
  • XMPP est fédéré et utilise un réseau un peu similaire à celui du courrier électronique ; les comptes sont créés sur les serveurs (c’est pourquoi les identifiants sont également similaires : nomutilisateur@serveur.tld), les clients se connectent ensuite à ces serveurs XMPP ; en plus de ça, vous pouvez avoir plusieurs clients connectés, en même temps, à votre compte et ils seront tous synchronisés en temps réel :) ;
  • il y a déjà une grande communauté, avec des serveurs sérieux qui peuvent gérer des millions de connexions simultanément sans aucun problème (ejabberd <3).

C’est aussi un gros avantage pour Movim. Je n’ai pas à m’occuper de tous les problèmes de réseau. C’est « juste » un client simple et stupide qui se connecte aux serveurs XMPP, en obtient du contenu et leur en envoie.

Si vous comparez cette solution avec d’autres solutions de réseau fédéré telles que Mastodon ou Diaspora, il y a là une grande différence : pour Movim, les comptes sont sur un serveur distinct. Je n’ai donc pas besoin de créer une autre API pour communiquer avec Movim. Tout le monde peut échanger avec Movim en implémentant simplement XMPP (et il y a déjà beaucoup de bibliothèques et de solutions dans la nature pour le faire).

OK, nous avons choisi le protocole, maintenant nous devons construire le back‐end.

Un peu d’histoire

J’ai créé Movim en 2008 afin d’apprendre à programmer et essayer de construire par la même occasion une plate‐forme sociale sur laquelle j’aimerais échanger avec mes proches. Ayant choisi d’apprendre le langage PHP par la même occasion j’ai tout naturellement choisi celui‐ci pour commencer les travaux.

Avec les connaissances acquises au cours de mes études, l’aide d’un ami (Etenil, si tu me lis…) et de ce que j’ai pu apprendre de façon autodidacte j’ai progressivement amélioré Movim et rajouté les nombreuses fonctionnalités qui me paraissaient intéressantes pour construire une plate‐forme sociale digne de ce nom.

Puis au cours de l’été 2014 j’ai décidé d’entièrement réécrire le cœur de Movim afin d’en faire une plate‐forme entièrement temps réel. En effet, jusqu’ici le projet était construit sur une « émulation » de temps réel construite au dessus de HTTP via les connections XMPP (en utilisant l’extension BOSH).

Ces changements apportèrent également une importante réécriture de l’architecture interne et d’une refonte de l’interface utilisateur.

À cette période un nouveau cadriciel commençait à faire parler de lui au sein de la communauté. ReactPHP permettait en effet de construire très facilement des architectures entièrement en temps réel en PHP et offrait tout ce que je recherchais pour cette réécriture.

Un démon, quelques tuyaux et voilà !

ReactPHP est un ensemble d’outils s’interconnectant entre eux et permettant de créer toutes sortes d’architectures fonctionnant entièrement en temps réel.

ReactPHP is handling most of the core features of Movim

J’utilise à ce jour les modules suivants :

  • react/event-loop, le cœur de React, s’occupant de la gestion de toutes les entrées‐sorties ;
  • react/dns, un résolveur DNS asynchrone ;
  • react/promise-timer, pour exécuter périodiquement des évènements ;
  • react/socket, pour se connecter à XMPP en utilisant des sockets TCP (avec une couche de chiffrement TLS par dessus) ;
  • react/child-process, pour lancer et gérer des sous‐processus ;
  • react/stream, afin de connecter toutes ces choses ensemble ;
  • react/zmq, une bibliothèque ZeroMQ pour pouvoir gérer efficacement les communications au sein de Movim.

Il m’a fallu ensuite quelques mois de recherche avant de trouver une architecture stable, qui n’a que peu changé par la suite.

Rentrons un peu dans les détails.

Toute la structure de Movim est prise en charge par un démon central (qui s’appelle daemon.php, c’est fou !). Ce démon s’occupe de tous les WebSockets des navigateurs des utilisateurs (mobiles et bureau) et lance un sous‐processus pour chaque utilisateur connecté. Finalement, il se comporte comme un routeur tout bête qui transfère les messages entre les WebSockets des utilisateurs et leurs processus respectifs

Cette architecture offre plusieurs avantages :

  • les sessions utilisateur sont isolées et n’influent pas sur les performances les unes des autres ;
  • elles peuvent être contrôlées plus facilement (tuer une session ne supprimera pas les autres) ;
  • le démon principal est minimal (il agit comme un simple routeur).

Cela présente néanmoins un inconvénient : la consommation de mémoire est supérieure. Le code est chargé plusieurs fois entre les différents sous‐processus. Il faut compter environ 10 à 20 Mio par utilisateur connecté. La situation s’est bien améliorée depuis les dernières versions puisque la consommation mémoire de Movim lui‐même a été réduite en retirant des dépendances et en mettant à jour PHP (PHP 7.0+). La consommation mémoire reste un point d’amélioration pour les versions à venir puisqu’elle pourrait devenir un goulot d’étranglement. Le cadriciel peut facilement supporter des milliers de connexions simultanées mais la mémoire vive manquera bien avant d’y arriver.

Chacun des ces sous processus se connecte au serveur XMPP de l’utilisateur puis prend en charge toutes ses communications. Il se connecte aussi à la base de données SQL commune qui fait office de cache pour chaque compte et permet l’échange de données entre eux (via la découverte de ressources publiques par exemple)

The Movim simplified architecture

Pour finir, ces processus gèrent aussi tout ce qui est relatif au frontal, mais cette partie sera expliquée plus en détail dans un article à venir.

Optimisations

Certaines optimisations ont été faites pour améliorer les performances globales de cette architecture. En voici les trois principales, celles qui je pense, ont eu le plus grand impact sur le projet.

Analyseur de flux XML

Une connexion XMPP peut être ramenée à un flux XML bidirectionnel. Le client envoie des requêtes XML (appelées stanzas) et analyse (d’un point de vue lexical) les requêtes entrantes. Le point important ici est que les requêtes entrantes font partie d’un seul et même « document » XML. À l’origine, Movim détectait chacune de ces stanzas et les analysait séparément.

L’analyseur a donc été remanié pour travailler en flux (voir analyseur syntaxique XML). Cela permet à Movim de préparer les stanzas entrantes et de lancer les événements qui leur sont relatifs dès que les premières balises XML sont reçus dans le socket. Le petit changement a vraiment amélioré les performances XMPP globales du projet. En particulier pendant la phase de connexion puisque Movim peut maintenant traiter plusieurs milliers de stanzas en quelques secondes.

Hello ZeroMQ !

Les communications entre le démon principal et les sous‐processus (qu’on appelle « linkers » dans Movim) sont à l’origine de simples stdin/stout. Cela a créé des problèmes de tampons et de performance et j’ai finalement choisi d’utiliser un outil spécifique à la tâche : ZeroMQ.

À chaque fois que le démon principal invoque un linker pour un utilisateur, il crée deux flux IPC dédiés (un pour les messages entrants et un pour les messages sortants) puis gère tout ce qui les traverse.

Cela m’a permis d’éviter la création de certains tampons dédiés au transit de messages et ainsi d’améliorer les performances globales, en particulier pour la partie interface utilisateur.

ZeroMQ est aussi très léger et est déjà disponible et empaqueté sur la majeure partie des distributions GNU/Linux.

De Modl à Eloquent

Movim dépendait au début d’un ORM spécifiquement créé pour le projet (Modl). La version qui arrive (0.14) utilisera la bibliothèque reconnue Eloquent (utilisée par le cadriciel Laravel).

Ce changement m’a permis d’utiliser des fonctionnalités comme le eager loading et le lazy loading, mais aussi d’écrire des migrations proprement et d’optimiser certaines requêtes.

Plus d’informations dans l’article dédié.

Ce que j’ai appris

Après toutes ces années à travailler sur ce project temps réel, je peux maintenant tirer certaines conclusions sur les choix et changements que j’ai réalisés :

  • PHP n’est pas un problème la plupart du temps : PHP est rapide, vraiment rapide ; la plupart des optimisations que j’ai obtenues étaient liées à la façon dont je gérais les flux et leur contenu ainsi qu’aux requêtes dans la BDD ; passer à PHP 7 puis aux versions suivantes a un peu amélioré les performances, mais le gain a été négligeable par rapport à ce qui a découlé des autres changements réalisés dans le code ;
  • chercher le goulot d’étranglement : quand on travaille en temps réel, même si certaines parties sont gérées par des promesses et autres systèmes asynchrones, il y a toujours du code synchrone et donc bloquant ; il faut s’assurer que ce code n’est pas « trop lent ». Dans Movim, par exemple, les requêtes BDD sont toujours considérées comme bloquantes (c’est une autre optimisation qui pourrait être apportée…) ce qui fait qu’une requête qui prend 200 ms à être déclenchée va retarder l’exécution du reste du code de 200 ms ;
  • tester en « conditions réelles » : je pensais que Movim était rapide jusqu’au moment où j’ai vu des utilisateurs galérer avec (Nik, si tu me lis…) ; certains utilisateurs de Movim avaient beaucoup plus de salons de discussion et avaient souscrit à beaucoup plus de flux que prévu, ce qui a créé de gros ralentissements, en particulier pendant la phase de connexion ; grâce à quelques optimisations bien pensées (et parfois très simples), les choses sont revenues à la normale ;
  • et peut‐être la plus importante de toutes : Keep It Simple!

J’ai l’impression que beaucoup de projets accordent trop d’importance au principe DRY — Don’t Repeat Yourself). Parfois il n’est pas nécessaire d’importer une bibliothèque entière, écrire une fonction qui correspond exactement à la situation peut faire l’affaire. Il est préférable de garder aussi peu de dépendances que possible.

Questionnez‐vous sur ce dont votre projet a besoin pour fonctionner. Est‐ce que tout est vraiment indispensable ?

Et pour finir, n’ayez pas peur d’un grand ménage de printemps de temps en temps (j’ai passé 50 heures à remplacer Modl par Eloquent) pour simplifier et nettoyer votre code si nécessaire.

Du coup, Movim est rapide ?

Movim est rapide. Dans certains cas, Movim est même plus rapide que certains clients XMPP natifs comme Pidgin ou Gajim. Movim est aussi plus rapide que certaines autres plates‐formes de discussion en ligne, de par son back‐end, mais aussi grâce à la façon dont son frontal est mis en œuvre. J’en reparlerai dans un prochain article.

Sur mon compte (400 contacts, 50 salons de discussion) s’authentifier et obtenir une interface réactive ne prend qu’une poignée de secondes, surtout sachant que les données viennent d’un serveur tiers (votre serveur XMPP) et sont re‐synchronisées pour certaines lorsque vous vous connectez.
Si vous voulez voir le résultat par vous‐même, faites un tour sur le site officiel. ;)

That’s all folks!

Commentaires : voir le flux atom ouvrir dans le navigateur

par edhelas, Yves Bourguignon, Xavier Teyssier, RoM1, Benoît Sibaud, Nils Ratusznik, Davy Defaud, palm123, Nÿco, Bruno Michel, M5oul

DLFP - Dépêches

LinuxFr.org

Entretien avec GValiente à propos de Butano

 -  16 avril - 

GValiente développe un SDK pour créer des jeux pour la console Game Boy Advance : Butano.Cet entretien revient sur son parcours et les raisons (...)


Nouveautés d'avril 2024 de la communauté Scenari

 -  11 avril - 

Scenari est un ensemble de logiciels open source dédiés à la production collaborative, publication et diffusion de documents multi-support. Vous (...)


Annuaire de projets libres (mais pas de logiciels)

 -  9 avril - 

Les communs sont une source énorme de partage !S’il est plutôt facile dans le monde francophone de trouver des ressources logicielles (Merci (...)


Les enchères en temps réel, un danger pour la vie privée mais aussi pour la sécurité européenne

 -  7 avril - 

Les enchères en temps réel, ou Real-Time Bidding (RTB), sont une technologie publicitaire omniprésente sur les sites web et applications mobiles (...)


XZ et liblzma: Faille de sécurité volontairement introduite depuis au moins deux mois

 -  31 mars - 

Andres Freund, un développeur Postgres, s’est rendu compte dans les derniers jours que xz et liblzma ont été corrompus par l’un des mainteneurs du (...)